Maximum product of 13 adjacent numbers - c#

List<int> arr = new List<int>();
long max = 0;
long mul = 1;
string abc = #"73167176531330624919225119674426574742355349194934
85861560789112949495459501737958331952853208805511
96983520312774506326239578318016984801869478851843
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450";
foreach (char a in abc)
{
if(arr.Count == 13)
{
arr.RemoveAt(0);
}
int value = (int)Char.GetNumericValue(a);
arr.Add(value);
if(arr.Count == 13)
{
foreach(int b in arr)
{
mul = mul * b;
if (mul > max)
{
max = mul;
}
}
mul = 1;
}
}
Console.WriteLine(max);
I am getting 5377010688 which is a wrong answer and when I am trying same logic with given example in project Euler it is working fine, please help me.
Don't say the answer just correct me where I am doing wrong or where the code is not running as it should.

The string constant, as it is written down like above, contains blanks and \r\n's, e.g. between the last '4' of the first line and the first '8' on the second line. Char.GetNumericValue() returns -1 for a blank.
Propably the character sequence with the highest product spans across adjacent lines in your string, therefore there are blanks in between, which count as -1, which disables your code in finding them.
Write your constant like this:
string abc = #"73167176531330624919225119674426574742355349194934" +
"85861560789112949495459501737958331952853208805511" +
"96983520312774506326239578318016984801869478851843" + etc.
The result is then 23514624000, I hope that's correct.

Don't say the answer just correct me where I am doing wrong or where
the code is not running as it should
You have included all characters into calculation but you should not do that. The input string also contains for example carriage return '\n' at the end of each line.
Your actual string look like this:
string abc = #"73167176531330624919225119674426574742355349194934\r\n
85861560789112949495459501737958331952853208805511\r\n
...
How to solve this? You should ignore these characters, one possible solution is to check each char if it is a digit:
if(!char.IsDigit(a))
{
continue;
}

Related

How to take digits from two different numbers and form a new one

I have the following problem here:My input is several lines of 2 digit numbers and I need to make a new number using the second digit of the first number and the first of the next one.
Example:
int linesOfNumbers = Convert.ToInt32(Console.ReadLine());
for(int i = 0,i<linesOfNumbers,i++)
{
int numbers = Conver.ToInt32(Console.ReadLine());
//that's for reading the input
}
I know how to separate the numbers into digits.My question is how to merge them.
For example if your input is 12 and 21 the output should be 22.
I like oRole's answer, but I think they're missing a couple things with the example input that you provided in your comment. I'll also point out some of the errors in the code that you have.
First off, if you're only given the input 12,23,34,45, then you don't need to call Console.ReadLine within your for loop. You've already gotten the input, you don't need to get any more (from what you've described).
Secondly, unless you're doing mathematical operations, there is no need to store numerical data as ints, keep it as a string, especially in this case. (What I mean is that you don't store Zip Codes in a database as a number, you store it as a string.)
Now, onto the code. You had the right way to get your data:
var listOfNumbers = Console.ReadLine();
At that point, listOfNumbers is equal to "12,23,34,45". If you iterate on that variable as a string, you'll be taking each individual character, including the commas. To get each of the numbers to operate on, you'll need to use string.Split.
var numbers = listOfNumbers.Split(',');
This turns that list into four different two character numbers (in string form). Now, you can iterate over them, but you don't need to worry about converting them to numbers as you're operating on the characters in each string. Also, you'll need a results collection to put everything into.
var results = new List<string>();
// Instead of the regular "i < numbers.Length", we want to skip the last.
for (var i = 0; i < numbers.Length - 1; i++)
{
var first = numbers[i];
var second = numbers[i + 1]; // This is why we skip the last.
results.Add(first[1] + second[0]);
}
Now your results is a collection of the numbers "22", "33", and "44". To get those back into a single string, you can use the helper method string.Join.
Console.WriteLine(string.Join(",", results));
You could use the string-method .Substring(..) to achieve what you want.
If you want to keep int-conversion in combination with user input, you could do:
int numA = 23;
int numB = 34;
int resultAB = Convert.ToInt16(numA.ToString().Substring(1, 1) + numB.ToString().Substring(0, 1));
Another option would be to take the users input as string values and to convert them afterwards like that:
string numC = "12";
string numD = "21";
int resultCD = Convert.ToInt16(numC.Substring(1, 1) + numD.Substring(0, 1));
I hope this code snippet will help you combining your numbers. The modulo operator (%) means: 53 / 10 = 5 Rest 3
This example shows the computation of the numbers 34 and 12
int firstNumber = 34 - (34 % 10) // firstNumber = 30
int secondNumber = 12 % 10; // secondNumber = 2
int combined = firstNumber + secondNumber; // combined = 32
EDIT (added reading and ouput code):
boolean reading = true;
List<int> numbers = new ArrayList();
while(reading)
{
try
{
int number = Convert.ToInt32(Console.ReadLine());
if (number > 9 && number < 100) numbers.Add(number);
else reading = false; // leave reading process if no 2-digit-number
}
catch (Exception ex)
{
// leave reading process by typing a character instead of a number;
reading = false;
}
}
if (numbers.Count() > 1)
{
List<int> combined = new ArrayList();
for (int i = 1; i <= numbers.Count(); i++)
{
combined.Add((numbers[i-1] % 10) + (numbers[i] - (numbers[i] % 10)));
}
//Logging output:
foreach (int combination in combined) Console.WriteLine(combination);
}
As you mention, if you already have both numbers, and they are always valid two digit integers, following code should work for you.
var num1 = 12;
var num2 = 22;
var result = (num2 / 10)*10 + (num1 % 10);
num2/10 returns the first digit of second number, and num1 % 10 returns the second digit of the first number.
The % and / signs are your savior.
If you want the 'ones' digit of a number (lets call it X), simply do X%10 - the remainder will be whatever number is in the 'ones' digit. (23%10=3)
If, instead, the number is two digits and you want the 'tens' digit, divide it by ten. (19/10=1).
To merge them, multiply the number you want to be in the 'tens' digit by ten, and add the other number to it (2*10+2=22)
There are other solutions like substring, etc and many one have already given it above. I am giving the solution VIA LINQ, note that this isn't efficient and it's recommended only for learning purpose here
int numA = 12;
int numB = 21 ;
string secondPartofNumA = numA.ToString().Select(q => new string(q,1)).ToArray()[1]; // first digit
string firstPartofNumB = numB.ToString().Select(q => new string(q,1)).ToArray()[0]; // second digit
string resultAsString = secondPartofNumA + firstPartofNumB;
int resultAsInt = Convert.ToInt32(resultAsString);
Console.WriteLine(resultAsString);
Console.WriteLine(resultAsInt);

Count Zeroes before the Decimal Point

I am trying to count how many zeroes are a before a decimal.
private void textBox1_TextChanged(object sender, EventArgs e)
{
decimal x = 0;
if (Decimal.TryParse(textBox1.Text, out x))
{
var y = 1000000;
var answer = x * y;
displayLabel2.Text = (x.ToString().Replace(".", "").TrimStart(new Char[] { '0' }) + "00").Substring(0, 2);
}
else
{
displayLabel2.Text = "error";
}
}
When I plug in (lets say) 7.2 I get an output that displays 72, which is what I want. Now I need another display. That initial 7.2 is being multiplied by 1000000. So the quotent of that would be 7,200,000.00. Now I need to some how count the 5 zeroes before the decimal point and display 5 for that. Then if I were to do .72. My Quotent would be 720,000.00. And I would need to display 4, for the 4 zeroes. And so on. Then I need to output that number to displayLabel5.Text
Here's a one line Linq you could try to count zeroes before the decimal. You can Split() first by the decimal then perform a Where().Count() to get the number of zeros.
using System;
using System.Linq;
public class Program
{
public static void Main()
{
string myString = (720000.00).ToString();
Console.WriteLine(myString.Split('.')[0].Where(d => d == '0').Count());
}
}
Results:
4
Demo
Quick and dirty code so be careful, but AFAIK this is the fastest way to do it.
// Input assuming you've sanitised it
string myInputString = "720000.00";
// Remove the decimals
myInputString = myInputString.Substring(0, myInputString.IndexOf("."));
// The count
int count = 0;
// Loop through and count occurrences
foreach (char c in myInputString)
{
if (c == "0")
{
count++;
}
}
Count is now 4.
Guarantee you this is faster than Regex ;-)
Edit: Sorry for the multiple edits, it's been a long day. Need coffee.
use a regular expression to find all the zeros before the period, then get the string length of that match.
Regex regex = new Regex(#"(0+)\.?");
string value1 = "7,200,000.00";
value1 = value1.Replace(",",""); //get rid of the commas
Match match = regex.Match(value1);
if (match.Success)
{
Console.WriteLine(match.Value.Length);
}
As always test the code because I wrote it just now here in this little text box and not in actual visual studio where I could compile and test it myself. But this should at least illustrate the methodology.
Edit:
slight tweak to the regex to account for the possibility that the number will not display a decimal point at all.

Create a numeric value from text

I have searched allot on google without any results I am looking for
I would like to get a numeric value from any string in C#
Ex.
var myString = "Oompa Loompa";
var numericoutput = convertStringToNumericValue(myString);
output/value of numericoutput is something like 612734818
so when I put in another string let say "C4rd1ff InTernaT!onal is # gr3at place#"
the int output will be something like 73572753.
The Values must stay constant, for example so if I enter the same text again of "Oompa Loompa" then I get 612734818 again.
I thought maybe in the way of using Font Family to get the char index of each character, but I don't know where to start with this.
The reason for this is so that I can use this number to generate an index out of a string with other data in it, and with the same input string, get that same index again to recall the final output string for validation.
Any help or point in the right direction would be greatly appreciated
Thanks to Tim I ended up doing the following:
var InputString = "My Test String ~!##$%^&*()_+{}:<>?|";
byte[] asciiBytes = Encoding.ASCII.GetBytes(InputString);
int Multiplier = 1;
int sum = 0;
foreach (byte b in asciiBytes)
{
sum += ((int)b) * Multiplier;
Multiplier++;
}
Obviously this will not work for 1000's of characters, but it is good enough for short words or sentences
int.MaxValue = 2 147 483 647
As an alternative to converting the string to it's bytes, and if a hash won't meet the requirements, here are a couple of shorter ways to accomplish getting a numeric value for a string:
string inputString = "My Test String ~!##$%^&*()_+{}:<>?|"
int multiplier = 0;
int sum = 0;
foreach (char c in inputString)
{
sum += ((int)c) * ++multiplier;
}
The above code outputs 46026, as expected. The only difference is it loops through the characters in the string and gets their ASCII value, and uses the prefix ++ operator (Note that multiplier is set to 0 in this case - which is also the default for int).
Taking a cue from Damith's comment above, you could do the same with LINQ. Simply replace the foreach above with:
sum = inputString.Sum(c => c * ++multiplier);
Finally, if you think you'll need a number larger than Int32.MaxValue, you can use an Int64 (long), like this:
string inputString = "My Test String ~!##$%^&*()_+{}:<>?|"
int multiplier = 0;
long largeSum = 0;
foreach (char c in inputString)
{
largeSum += ((int)c) * ++multiplier;
}

Constantly Incrementing String

So, what I'm trying to do this something like this: (example)
a,b,c,d.. etc. aa,ab,ac.. etc. ba,bb,bc, etc.
So, this can essentially be explained as generally increasing and just printing all possible variations, starting at a. So far, I've been able to do it with one letter, starting out like this:
for (int i = 97; i <= 122; i++)
{
item = (char)i
}
But, I'm unable to eventually add the second letter, third letter, and so forth. Is anyone able to provide input? Thanks.
Since there hasn't been a solution so far that would literally "increment a string", here is one that does:
static string Increment(string s) {
if (s.All(c => c == 'z')) {
return new string('a', s.Length + 1);
}
var res = s.ToCharArray();
var pos = res.Length - 1;
do {
if (res[pos] != 'z') {
res[pos]++;
break;
}
res[pos--] = 'a';
} while (true);
return new string(res);
}
The idea is simple: pretend that letters are your digits, and do an increment the way they teach in an elementary school. Start from the rightmost "digit", and increment it. If you hit a nine (which is 'z' in our system), move on to the prior digit; otherwise, you are done incrementing.
The obvious special case is when the "number" is composed entirely of nines. This is when your "counter" needs to roll to the next size up, and add a "digit". This special condition is checked at the beginning of the method: if the string is composed of N letters 'z', a string of N+1 letter 'a's is returned.
Here is a link to a quick demonstration of this code on ideone.
Each iteration of Your for loop is completely
overwriting what is in "item" - the for loop is just assigning one character "i" at a time
If item is a String, Use something like this:
item = "";
for (int i = 97; i <= 122; i++)
{
item += (char)i;
}
something to the affect of
public string IncrementString(string value)
{
if (string.IsNullOrEmpty(value)) return "a";
var chars = value.ToArray();
var last = chars.Last();
if(char.ToByte() == 122)
return value + "a";
return value.SubString(0, value.Length) + (char)(char.ToByte()+1);
}
you'll probably need to convert the char to a byte. That can be encapsulated in an extension method like static int ToByte(this char);
StringBuilder is a better choice when building large amounts of strings. so you may want to consider using that instead of string concatenation.
Another way to look at this is that you want to count in base 26. The computer is very good at counting and since it always has to convert from base 2 (binary), which is the way it stores values, to base 10 (decimal--the number system you and I generally think in), converting to different number bases is also very easy.
There's a general base converter here https://stackoverflow.com/a/3265796/351385 which converts an array of bytes to an arbitrary base. Once you have a good understanding of number bases and can understand that code, it's a simple matter to create a base 26 counter that counts in binary, but converts to base 26 for display.

Testing for repeated characters in a string

I'm doing some work with strings, and I have a scenario where I need to determine if a string (usually a small one < 10 characters) contains repeated characters.
`ABCDE` // does not contain repeats
`AABCD` // does contain repeats, ie A is repeated
I can loop through the string.ToCharArray() and test each character against every other character in the char[], but I feel like I am missing something obvious.... maybe I just need coffee. Can anyone help?
EDIT:
The string will be sorted, so order is not important so ABCDA => AABCD
The frequency of repeats is also important, so I need to know if the repeat is pair or triplet etc.
If the string is sorted, you could just remember each character in turn and check to make sure the next character is never identical to the last character.
Other than that, for strings under ten characters, just testing each character against all the rest is probably as fast or faster than most other things. A bit vector, as suggested by another commenter, may be faster (helps if you have a small set of legal characters.)
Bonus: here's a slick LINQ solution to implement Jon's functionality:
int longestRun =
s.Select((c, i) => s.Substring(i).TakeWhile(x => x == c).Count()).Max();
So, OK, it's not very fast! You got a problem with that?!
:-)
If the string is short, then just looping and testing may well be the simplest and most efficient way. I mean you could create a hash set (in whatever platform you're using) and iterate through the characters, failing if the character is already in the set and adding it to the set otherwise - but that's only likely to provide any benefit when the strings are longer.
EDIT: Now that we know it's sorted, mquander's answer is the best one IMO. Here's an implementation:
public static bool IsSortedNoRepeats(string text)
{
if (text.Length == 0)
{
return true;
}
char current = text[0];
for (int i=1; i < text.Length; i++)
{
char next = text[i];
if (next <= current)
{
return false;
}
current = next;
}
return true;
}
A shorter alternative if you don't mind repeating the indexer use:
public static bool IsSortedNoRepeats(string text)
{
for (int i=1; i < text.Length; i++)
{
if (text[i] <= text[i-1])
{
return false;
}
}
return true;
}
EDIT: Okay, with the "frequency" side, I'll turn the problem round a bit. I'm still going to assume that the string is sorted, so what we want to know is the length of the longest run. When there are no repeats, the longest run length will be 0 (for an empty string) or 1 (for a non-empty string). Otherwise, it'll be 2 or more.
First a string-specific version:
public static int LongestRun(string text)
{
if (text.Length == 0)
{
return 0;
}
char current = text[0];
int currentRun = 1;
int bestRun = 0;
for (int i=1; i < text.Length; i++)
{
if (current != text[i])
{
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = text[i];
}
currentRun++;
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Now we can also do this as a general extension method on IEnumerable<T>:
public static int LongestRun(this IEnumerable<T> source)
{
bool first = true;
T current = default(T);
int currentRun = 0;
int bestRun = 0;
foreach (T element in source)
{
if (first || !EqualityComparer<T>.Default(element, current))
{
first = false;
bestRun = Math.Max(currentRun, bestRun);
currentRun = 0;
current = element;
}
}
// It's possible that the final run is the best one
return Math.Max(currentRun, bestRun);
}
Then you can call "AABCD".LongestRun() for example.
This will tell you very quickly if a string contains duplicates:
bool containsDups = "ABCDEA".Length != s.Distinct().Count();
It just checks the number of distinct characters against the original length. If they're different, you've got duplicates...
Edit: I guess this doesn't take care of the frequency of dups you noted in your edit though... but some other suggestions here already take care of that, so I won't post the code as I note a number of them already give you a reasonably elegant solution. I particularly like Joe's implementation using LINQ extensions.
Since you're using 3.5, you could do this in one LINQ query:
var results = stringInput
.ToCharArray() // not actually needed, I've left it here to show what's actually happening
.GroupBy(c=>c)
.Where(g=>g.Count()>1)
.Select(g=>new {Letter=g.First(),Count=g.Count()})
;
For each character that appears more than once in the input, this will give you the character and the count of occurances.
I think the easiest way to achieve that is to use this simple regex
bool foundMatch = false;
foundMatch = Regex.IsMatch(yourString, #"(\w)\1");
If you need more information about the match (start, length etc)
Match match = null;
string testString = "ABCDE AABCD";
match = Regex.Match(testString, #"(\w)\1+?");
if (match.Success)
{
string matchText = match.Value; // AA
int matchIndnex = match.Index; // 6
int matchLength = match.Length; // 2
}
How about something like:
string strString = "AA BRA KA DABRA";
var grp = from c in strString.ToCharArray()
group c by c into m
select new { Key = m.Key, Count = m.Count() };
foreach (var item in grp)
{
Console.WriteLine(
string.Format("Character:{0} Appears {1} times",
item.Key.ToString(), item.Count));
}
Update Now, you'd need an array of counters to maintain a count.
Keep a bit array, with one bit representing a unique character. Turn the bit on when you encounter a character, and run over the string once. A mapping of the bit array index and the character set is upto you to decide. Break if you see that a particular bit is on already.
/(.).*\1/
(or whatever the equivalent is in your regex library's syntax)
Not the most efficient, since it will probably backtrack to every character in the string and then scan forward again. And I don't usually advocate regular expressions. But if you want brevity...
I started looking for some info on the net and I got to the following solution.
string input = "aaaaabbcbbbcccddefgg";
char[] chars = input.ToCharArray();
Dictionary<char, int> dictionary = new Dictionary<char,int>();
foreach (char c in chars)
{
if (!dictionary.ContainsKey(c))
{
dictionary[c] = 1; //
}
else
{
dictionary[c]++;
}
}
foreach (KeyValuePair<char, int> combo in dictionary)
{
if (combo.Value > 1) //If the vale of the key is greater than 1 it means the letter is repeated
{
Console.WriteLine("Letter " + combo.Key + " " + "is repeated " + combo.Value.ToString() + " times");
}
}
I hope it helps, I had a job interview in which the interviewer asked me to solve this and I understand it is a common question.
When there is no order to work on you could use a dictionary to keep the counts:
String input = "AABCD";
var result = new Dictionary<Char, int>(26);
var chars = input.ToCharArray();
foreach (var c in chars)
{
if (!result.ContainsKey(c))
{
result[c] = 0; // initialize the counter in the result
}
result[c]++;
}
foreach (var charCombo in result)
{
Console.WriteLine("{0}: {1}",charCombo.Key, charCombo.Value);
}
The hash solution Jon was describing is probably the best. You could use a HybridDictionary since that works well with small and large data sets. Where the letter is the key and the value is the frequency. (Update the frequency every time the add fails or the HybridDictionary returns true for .Contains(key))

Categories