For a given word calculate the number of possible anagrams.
The resulting words do not have to exist in the dictionary.
Anagrams do not have to be repeated and anagrams do not have to be generated, only their number calculated.
The last test is not working and I do not know how should I make it work. Can you help me, please?
Here is my code:
using System;
static void Main(string[] args)
{
string word = Console.ReadLine();
int wordLenth = word.Length;
int sameLetter = 1;
for (int i=0;i<wordLenth;i++)
{
for (int j=i+1;j<wordLenth;j++)
{
if (word[i]==word[j])
{
sameLetter++;
}
}
}
int firstResult=1, secondResult=1, lastResult;
for (int i=1; i <= wordLenth; i++)
{
firstResult *= i;
}
for (int i = 1; i <= sameLetter; i++)
{
secondResult *= i;
}
lastResult = firstResult / secondResult;
Console.WriteLine(lastResult);
}
Results:
Compilation successfully executed.
Test 1: Correctly calculate the number of anagrams for "abc" - successful
Test 2: Correctly calculate the number of anagrams for "abc" - success
Test 3: Correctly calculates the number of anagrams for "aaab" - failed
Expected results: "4"
Results obtained: "1"
The submitted solution does not correctly calculate the number of unique anagrams if there are repeating letters.
If you have word of length n with m distinct letters w1, ..., wm where wi is occurence of ith letter,
the number of possible anagrams is
Math:
N = n! / w1! / w2! / ... / wm!
For instance:
For abc we have n = 3, m = 3, w1 = w2 = w3 = 1:
N = 3! / 1! / 1! / 1! = 6 / 1 / 1 / 1 = 6
For aaab we have n = 4, m = 2, w1 = 3, w2 = 1:
N = 4! / 3! / 1! = 24 / 6 / 1 = 4
Code:
using System.Linq;
using System.Numerics;
...
private static BigInteger Factorial(int value) {
BigInteger result = 1;
for (int i = 2; i <= value; ++i)
result *= i;
return result;
}
private static BigInteger CountAnagrams(string value) {
if (string.IsNullOrEmpty(value))
return 1;
return value
.GroupBy(c => c)
.Aggregate(Factorial(value.Length), (s, group) => s / Factorial(group.Count()));
}
Demo: (Fiddle)
string[] tests = new string[] {
"a",
"aaa",
"abc",
"aaab",
"abracadabra",
"stackoverflow",
};
string report = string.Join(Environment.NewLine, tests
.Select(test => $"{test,20} => {CountAnagrams(test)}"));
Console.Write(report);
Outcome:
a => 1
aaa => 1
abc => 6
aaab => 4
abracadabra => 83160
stackoverflow => 3113510400
Edit: If you are not allowed to use System.Numerics and System.Linq you can try using long:
private static long Factorial(int value)
{
long result = 1;
for (int i = 2; i <= value; ++i)
result *= i;
return result;
}
private static long CountAnagrams(string value)
{
if (string.IsNullOrEmpty(value))
return 1L;
Dictionary<char, int> groups = new Dictionary<char, int>();
foreach (var c in value)
if (groups.TryGetValue(c, out int v))
groups[c] += 1;
else
groups.Add(c, 1);
long result = Factorial(value.Length);
foreach (int v in groups.Values)
result /= Factorial(v);
return result;
}
Related
I've got a programing problem.
I've been trying to do something like a probability calculator in c#, for that I need a certain type of factorial. I know how to program factorial, but I need
sum of all the factorials from zero to some given number.
Suppose the input number is some constant r, what I want is:
0! + 1! +2! + ... + (r-1)! + r!
This is what I've got so far, but still does not work:
double a, j, k = 1, sum = 1, l = 1;
for (a = 1; a <= f; a ++)
{
for (j = 1; j <= a; j++)
{
l = k * j;
}
sum = sum + l;
}
Console.WriteLine(sum);
One simple for loop is enough. Since factorial grows fast, let's use BigInteger type;
however, if you want, you can change all BigInteger into double:
using System.Numerics;
...
// 0! + 1! + 2! + ... + value!
public static BigInteger MyFunc(int value) {
if (value < 0)
throw new ArgumentOutOfRangeException(nameof(value));
BigInteger result = 1;
BigInteger factorial = 1;
for (int i = 1; i <= value; ++i)
result += (factorial *= i);
return result;
}
Demo:
using System.Linq;
...
int[] tests = new int[] {
0, 1, 2, 3, 4, 5, 6, 7
};
string report = string.Join(Environment.NewLine,
tests.Select(x => $"{x} => {MyFunc(x),4}"));
Console.WriteLine(report);
Outcome:
0 => 1
1 => 2
2 => 4
3 => 10
4 => 34
5 => 154
6 => 874
7 => 5914
My codes are like below.
I just want to try to convert number to binary and summarize binary numbers as if they are decimal ones, e.g. the desired outcome for 3 is 22:
1 -> 1
2 -> 10
3 -> 11
-------
22 == 1 + 10 + 11
But number array is growing and the code blowing :)
static void Main(string[] args)
{
long deger = 1;
for (int i = 0; i < 1000000; i++)
{
deger *= (deger + 1);
int result = solve(deger);
Console.WriteLine(result);
}
}
public static int solve(long a)
{
ulong[] lastValue = new ulong[a];
for (int i = 1; i < a; i++)
{
var binary = Convert.ToString(i, 2);
lastValue[i] = Convert.ToUInt64(binary);// this part gives an error
}
var result = lastValue.Aggregate((t, c) => t + c);
return (int)result;
}
Well, UInt64 is not large enough; you can try either BigInteger or you may sum up strings:
private string MyBinarySum(string left, string right) {
var x = left
.PadLeft(Math.Max(left.Length, right.Length) + 1, '0')
.Reverse()
.Select(c => c - '0')
.ToArray();
var y = right
.PadLeft(Math.Max(left.Length, right.Length) + 1, '0')
.Reverse().Select(c => c - '0')
.ToArray();
StringBuilder sb = new StringBuilder(left.Length);
int shift = 0;
for (int i = 0; i < x.Length; ++i) {
int v = x[i] + y[i] + shift;
shift = v / 2;
v = v % 2;
sb.Append((char)('0' + v));
}
return String.Concat(sb.ToString().TrimEnd('0').Reverse());
}
Then, with a help of Linq
var result = Enumerable
.Range(0, 1000000)
.Select(item => Convert.ToString(item, 2))
.Aggregate((sum, item) => MyBinarySum(sum, item));
Console.Write(result);
Outcome:
111010001101010010010101110011011100000
which is beyond UInt64.MaxValue == 18446744073709551615
Look at UInt64.MaxValue and UInt64.MinValue.
They defined as 18446744073709551615 and 0 corresponding.
Given a large list of integers (more than 1 000 000 values) find how many ways there are of selecting two of them that add up to 0.... Is the question
What I have done is create a positive random integer list:
Random pos = new Random();
int POSNO = pos.Next(1, 1000000);
lstPOS.Items.Add(POSNO);
lblPLus.Text = lstPOS.Items.Count.ToString();
POSCount++;
And created a negative list:
Random neg = new Random();
int NEGNO = neg.Next(100000, 1000000);
lstNEG.Items.Add("-" + NEGNO);
lblNegative.Text = lstNEG.Items.Count.ToString();
NegCount++;
To do the sum checking I am using:
foreach (var item in lstPOS.Items)
{
int POSItem = Convert.ToInt32(item.ToString());
foreach (var negItem in lstNEG.Items)
{
int NEGItem = Convert.ToInt32(negItem.ToString());
int Total = POSItem - NEGItem;
if (Total == 0)
{
lstADD.Items.Add(POSItem + "-" + NEGItem + "=" + Total);
lblAddition.Text = lstADD.Items.Count.ToString();
}
}
}
I know this is not the fastest route. I have considered using an array. Do you have any suggestions?
Let's see; your array is something like this:
int[] data = new int[] {
6, -2, 3, 2, 0, 0, 5, 7, 0, -2
};
you can add up to zero in two different ways:
a + (-a) // positive + negative
0 + 0 // any two zeros
in the sample above there're five pairs:
-2 + 2 (two pairs): [1] + [3] and [3] + [9]
0 + 0 (three pairs): [4] + [5], [4] + [8] and [5] + [8]
So you have to track positive/negative pairs and zeros. The implementation
Dictionary<int, int> positives = new Dictionary<int, int>();
Dictionary<int, int> negatives = new Dictionary<int, int>();
int zeros = 0;
foreach(var item in data) {
int v;
if (item < 0)
if (negatives.TryGetValue(item, out v))
negatives[item] = negatives[item] + 1;
else
negatives[item] = 1;
else if (item > 0)
if (positives.TryGetValue(item, out v))
positives[item] = positives[item] + 1;
else
positives[item] = 1;
else
zeros += 1;
}
// zeros: binomal coefficent: (2, zeros)
int result = zeros * (zeros - 1) / 2;
// positive/negative pairs
foreach (var p in positives) {
int n;
if (negatives.TryGetValue(-p.Key, out n))
result += n * p.Value;
}
// Test (5)
Console.Write(result);
Note, that there's no sorting, and dictionaries (i.e. hash tables) are used for positives and negatives so the execution time will be linear, O(n); the dark side of the implementation is that two additional structures (i.e. additional memory) required. In your case (millions integers only - Megabytes) you have that memory.
Edit: terser, but less readable Linq solution:
var dict = data
.GroupBy(item => item)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count());
int result = dict.ContainsKey(0) ? dict[0] * (dict[0] - 1) / 2 : 0;
result += dict
.Sum(pair => pair.Key > 0 && dict.ContainsKey(-pair.Key) ? pair.Value * dict[-pair.Key] : 0);
Fastest way without sorting!.
First of all you know that the sum of two integers are only 0 when they have equal absolute value but one is negative and the other is positive. So you dont need to sort. what you need is to Intersect positive list with negative list (by comparing absolute value). the result is numbers that ended up 0 sum.
Intersect has time complexity of O(n+m) where n is size of first list and m is size of second one.
private static void Main(string[] args)
{
Random random = new Random();
int[] positive = Enumerable.Range(0, 1000000).Select(n => random.Next(1, 1000000)).ToArray();
int[] negative = Enumerable.Range(0, 1000000).Select(n => random.Next(-1000000, -1)).ToArray();
var zeroSum = positive.Intersect(negative, new AbsoluteEqual());
foreach (var i in zeroSum)
{
Console.WriteLine("{0} - {1} = 0", i, i);
}
}
You also need to use this IEqualityComparer.
public class AbsoluteEqual : IEqualityComparer<int>
{
public bool Equals(int x, int y)
{
return (x < 0 ? -x : x) == (y < 0 ? -y : y);
}
public int GetHashCode(int obj)
{
return obj < 0 ? (-obj).GetHashCode() : obj.GetHashCode();
}
}
You tried to avoid check two numbers that are close (1, 2 are close, 3, 4 are close), but you didn't avoid check like (-100000, 1), (-1, 100000). Time complexity is O(n^2).
To avoid that you need to sort them first, then search from two direction.
var random = new Random();
var input = Enumerable.Range(1, 100).Select(_ => random.Next(200) - 100).ToArray();
Array.Sort(input); // This causes most computation. Time Complexity is O(n*log(n));
var expectedSum = 0;
var i = 0;
var j = input.Length - 1;
while (i < j) // This has liner time complexity O(n);
{
var result = input[i] + input[j];
if(expectedSum == result)
{
var anchori = i;
while (i < input.Length && input[i] == input[anchori] )
{
i++;
}
var anchorj = j;
while (j >= 0 && input[j] == input[anchorj])
{
j--;
}
// Exclude (self, self) combination
Func<int, int, int> combination = (n, k) =>
{
var mink = k * 2 < n ? k : n - k;
return mink == 0 ? 1
: Enumerable.Range(0, mink).Aggregate(1, (x, y) => x * (n - y))
/ Enumerable.Range(1, mink).Aggregate((x, y) => x * y);
};
var c = i < j ? (i - anchori) * (anchorj - j) : combination(i - anchori, 2);
for (int _ = 0; _ < c; _++)
{
// C# 6.0 String.Format
Console.WriteLine($"{input[anchori]}, {input[anchorj]}");
}
}
else if(result < expectedSum) {
i++;
}
else if(result > expectedSum) {
j--;
}
}
Here is another solution using (huh) LINQ. Hope the code is self explanatory
First some data
var random = new Random();
var data = new int[1000000];
for (int i = 0; i < data.Length; i++) data[i] = random.Next(-100000, 100000);
And now the solution
var result = data
.Where(value => value != int.MinValue)
.GroupBy(value => Math.Abs(value), (key, values) =>
{
if (key == 0)
{
var zeroCount = values.Count();
return zeroCount * (zeroCount - 1) / 2;
}
else
{
int positiveCount = 0, negativeCount = 0;
foreach (var value in values)
if (value > 0) positiveCount++; else negativeCount++;
return positiveCount * negativeCount;
}
})
.Sum();
Theoretically the above should have O(N) time and O(M) space complexity, where M is the count of the unique absolute values in the list.
At first user gives a number (n) to program, for example 5.
the program must find the smallest number that can be divided to n (5).
and this number can only consist of digits 0 and 9 not any other digits.
for example if user gives 5 to program.
numbers that can be divided to 5 are:
5, 10, 15, 20, 25, 30, ..., 85, 90, 95, ...
but 90 here is the smallest number that can be divided to 5 and also consist of digits (0 , 9). so answer for 5 must be 90.
and answer for 9 is 9, because it can be divided to 9 and consist of digit (9).
my code
string a = txtNumber.Text;
Int64 x = Convert.ToInt64(a);
Int64 i ,j=1,y=x;
bool t = false;
for (i = x + 1; t == false; i++)
{
if (i % 9 == 0 && i % 10 == 0 && i % x == 0)
{
j = i;
for (; (i /= 10) != 0; )
{
i /= 10;
if (i == 0)
t = true;
continue;
}
}
}
lblAnswer.Text = Convert.ToString(j);
If you're happy to go purely functional then this works:
Func<IEnumerable<long>> generate = () =>
{
Func<long, IEnumerable<long>> extend =
x => new [] { x * 10, x * 10 + 9 };
Func<IEnumerable<long>, IEnumerable<long>> generate2 = null;
generate2 = ns =>
{
var clean = ns.Where(n => n > 0).ToArray();
return clean.Any()
? clean.Concat(generate2(clean.SelectMany(extend)))
: Enumerable.Empty<long>();
};
return generate2(new[] { 9L, });
};
Func<long, long?> f = n =>
generate()
.Where(x => x % n == 0L)
.Cast<long?>()
.FirstOrDefault();
So rather than iterate through all possible values and test for 0 & 9 and divisibility, this just generates only numbers with 0 & 9 and then only tests for visibility. It is much faster this way.
I can call it like this:
var result = f(5L); // 90L
result = f(23L); //990909L
result = f(123L); //99999L
result = f(12321L); //90900999009L
result = f(123212L); //99909990090000900L
result = f(117238L); //990990990099990990L
result = f(1172438L); //null == No answer
These results are super fast. f(117238L) returns a result on my computer in 138ms.
You can try this way :
string a = txtNumber.Text;
Int64 x = Convert.ToInt64(a);
int counter;
for (counter = 1; !isValid(x * counter); counter++)
{
}
lblAnswer.Text = Convert.ToString(counter*x);
code above works by searching multiple of x incrementally until result that satisfy criteria : "consist of only 0 and or 9 digits" found. By searching only multiple of x, it is guaranteed to be divisible by x. So the rest is checking validity of result candidate, in this case using following isValid() function :
private static bool isValid(int number)
{
var lastDigit = number%10;
//last digit is invalid, return false
if (lastDigit != 0 & lastDigit != 9) return false;
//last digit is valid, but there is other digit(s)
if(number/10 >= 1)
{
//check validity of digit(s) before the last
return isValid(number/10);
}
//last digit is valid, and there is no other digit. return true
return true;
}
About strange empty for loop in snippet above, it is just syntactic sugar, to make the code a bit shorter. It is equal to following while loop :
counter = 1;
while(!isValid(input*counter))
{
counter++;
}
Use this simple code
int inputNumber = 5/*Or every other number, you can get this number from input.*/;
int result=1;
for (int i = 1; !IsOk(result,inputNumber); i++)
{
result = i*inputNumber;
}
Print(result);
IsOk method is here:
bool IsOk(int result, int inputNumber)
{
if(result%inputNumber!=0)
return false;
if(result.ToString().Replace("9",string.Empty).Replace("0",string.Empty).Length!=0)
return false;
return true;
}
My first solution has very bad performance, because of converting a number to string and looking for characters '9' and '0'.
New solution:
My new solution has very good performance and is a technical approach since of using Breadth-first search(BFS).
Algorithm of this solution:
For every input number, test 9, if it is answer print it, else add 2 child numbers (90 & 99) to queue, and continue till finding answer.
int inputNumber = 5;/*Or every other number, you can get this number from input.*/
long result;
var q = new Queue<long>();
q.Enqueue(9);
while (true)
{
result = q.Dequeue();
if (result%inputNumber == 0)
{
Print(result);
break;
}
q.Enqueue(result*10);
q.Enqueue(result*10 + 9);
}
Trace of number creation:
9
90,99
900,909,990,999
9000,9009,9090,9099,9900,9909,9990,9999
.
.
.
I wrote this code for console, and i used goto command however it is not prefered but i could not write it with only for.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace main
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter your number");
Int64 x = Convert.ToInt64(Console.ReadLine());
Int64 y, j, i, k, z = x;
x = x + 5;
loop:
x++;
for (i = 0, y = x; y != 0; i++)
y /= 10;
for (j = x, k = i; k != 0; j /= 10, k--)
{
if (j % 10 != 9)
if (j % 10 != 0)
goto loop;
}
if (x % z != 0)
goto loop;
Console.WriteLine("answer:{0}",x);
Console.ReadKey();
}
}
}
When solving an interview question
Question
A six digit number need to be found in such a manner when it is multiplied by an integer between 2 and 9 gives the original six digit number when its digits are reversed.
Example:
Suppose I multiply 219978 * 4 i get 879912 ,when reverse 879912 I will get 219978 back.
I solved it using
for (long l = 100000; l < 999999; l++)
{
var num = l.ToString();
for (int i = 3; i < 9; i++)
{
var mul = l * i;
string str = mul.ToString();
char[] splitDigits = str.ToCharArray();
string reversedDigit =
new string(splitDigits.Reverse().ToArray());
if (reversedDigit.CompareTo(num) == 0)
{
Console.WriteLine("{0} * {1}= {2},
when multiplied {3} ", num, i, mul,reversedDigit);
}
}
}
The original task was to solve it using linq. I have bit confusion in handling temp calculations for example
when i use
var = from l in Enumerable.Range(100000,999999)
from i in Enumerable.Range(3,9)
What is the way to handle temporary calculations like var num = l.ToString(),etc in linq.It confused me a lot to finish it in Linq.Help is appreciated.
You want let...
// NOTE: buggy; see below
var qry = from l in Enumerable.Range(100000, 999999)
from i in Enumerable.Range(3, 9)
let s = l.ToString()
let t = (l * i).ToString()
where s.Reverse().SequenceEqual(t)
select new { l, i };
var a = qry.First();
Console.WriteLine("an answer...");
Console.WriteLine("{0} x {1} = {2}", a.l, a.i, a.l * a.i);
Console.WriteLine("all answers...");
foreach (var row in qry)
{
Console.WriteLine("{0} x {1} = {2}", row.l, row.i, row.l * row.i);
}
with first answer (note the inclusion of 9 is taken from your original version of the code, but it may be desirable to use Range(3,8) instead):
109989 x 9 = 989901
Optimised version (and correct range):
var qry = from l in Enumerable.Range(100000, 999999 - 100000)
let s = l.ToString()
let sReversed = new string(s.Reverse().ToArray())
let wanted = int.Parse(sReversed)
from i in Enumerable.Range(3, 8 - 3)
where l * i == wanted
select new { l, i };
This reduces the number of strings created, uses integer equality, and correctly uses the range (the second parameter to Range is the count, not the end).
Here's another solution that matches the problem statement with a few helper methods for clarity (which could be moved into the original linq query):
private static IEnumerable<int> SixDigitNumbers = Enumerable.Range(100000, (999999 - 100000));
private static IEnumerable<int> Multipliers = Enumerable.Range(2, 8);
static void Main(string[] args)
{
var Solutions = from OriginalNumber in SixDigitNumbers
from Multiplier in Multipliers
let MultipliedNumber = (OriginalNumber * Multiplier)
where MultipliedNumber < 999999 && ResultIsNumericPalindrome(OriginalNumber, Multiplier)
select new { MultipliedNumber, OriginalNumber, Multiplier };
var AllSolutions = Solutions.ToList();
}
private static string Reverse(string Source)
{
return new String(Source.Reverse().ToArray());
}
private static bool ResultIsNumericPalindrome(int Original, int Multiplier)
{
return (Original.ToString() == Reverse((Original * Multiplier).ToString()));
}
Here are ALL of the solutions:
{ MultipliedNumber = 989901, OriginalNumber = 109989, Multiplier = 9 }
{ MultipliedNumber = 879912, OriginalNumber = 219978, Multiplier = 4 }
Be careful with Enumerable.Range - I see one person responding to this question made the mistake of excluding two numbers requested in the problem statement.