So I have a list of ulong prime numbers, with variable lengths.
Ex: 2,5,7,3
And I want to create every multiplying combination, excluding ALL the numbers multiplied together.
(2*5*7*3 in this case).
Ex: 2,3,5,6,7,10,14,15,21,30,35,42,70,105.
I have tried a couple solutions using the "foreach" loop, but I just can't seem to get it. It seems too easy. What might be an efficient way to going about this?
My main issue that I run into is that when I add a new value to the list, the "foreach" loop causes an error because I changed it. I can't think of a way around that other than do a whole bunch of new lists. It seems to me like there should be a really simple, clean solution that I am just overcomplicating.
I tried the "Build-up" approaching, multiplying the base factors together, to create larger ones and so on, and the "Build-down" approaching, starting with the large number, and then factoring it (shown in my example). This is what I tried:
List<ulong> c, f;
ulong i;
//Some code then sets c to the factors (2, 3, 5, and 7)
//i is then set to the c set multiplied together (2*3*5*7)
//if the c is a factor, divide and add it to the new list f (the final list)
foreach (ulong u in c)
{
if (i % u == 0)
{
f.Add(i/u);
Console.WriteLine(i / u);
}
}
// Keep on dividing the numbers down, until you get the original factors added to the list
for (int j = 0; j < f.Count -1; j++)
{
foreach (ulong u in c)
{
foreach (ulong v in f)
{
if (v % u == 0)
{
if (v / u != 1 && !f.Contains(v / u))
{
f.Add(v / u);
}
}
}
}
}
Expected Output with input (2 5 7 3):
2
5
3
7
2 * 3 = 6
2 * 5 = 10
2 * 7 = 14
5 * 7 = 35
5 * 3 = 15
7 * 3 = 21
2 * 5 * 7 = 70
2 * 5 * 3 = 30
2 * 3 * 7 = 42
5 * 7 * 3 = 105
This works to get the numbers you want:
Func<IEnumerable<ulong>, IEnumerable<ulong>> f = null;
f = xs =>
{
if (xs.Any())
{
return f(xs.Skip(1))
.SelectMany(x =>
new [] { xs.First() * x, x });
}
else
{
return new ulong[] { 1 };
}
};
You use it like this:
var primes = new ulong[] { 2, 5, 7, 3 };
var results = f(primes)
.OrderBy(x => x)
.ToArray();
results = results
.Skip(1)
.Take(results.Length - 2)
.ToArray();
I had to do the Skip/Take to get rid of the two cases you wanted to avoid.
The result I get is:
If you'd like it as an (almost) one-liner here it is:
Func<IEnumerable<ulong>, IEnumerable<ulong>> f = null;
f = xs => xs.Any() ? f(xs.Skip(1)).SelectMany(x => new [] { xs.First() * x, x }) : new ulong[] { 1 };
The following code should give you exactly what you need with any number of items in your list
class Program
{
static void Main(string[] args)
{
MultiplyFactors(new List<ulong>() { 2, 3, 5, 7 });
Console.ReadLine();
}
public static void MultiplyFactors(List<ulong> numbers)
{
var factorCombinations = CreateSubsets(numbers.ToArray());
foreach (var factors in factorCombinations)
{
// set initial result to identity value. (any number multiplied by itself is 1)
ulong result = 1;
// multiply all factors in combination together
for (int i = 0; i < factors.Count(); i++)
{
result *= factors[i];
}
// Output for Display
Console.WriteLine(String.Format("{0}={1}", String.Join("x", factors), result));
}
}
private static List<T[]> CreateSubsets<T>(T[] originalArray)
{
// From http://stackoverflow.com/questions/3319586/getting-all-possible-permutations-from-a-list-of-numbers
var subsets = new List<T[]>();
for (int i = 0; i < originalArray.Length; i++)
{
int subsetCount = subsets.Count;
subsets.Add(new T[] {originalArray[i]});
for (int j = 0; j < subsetCount; j++)
{
T[] newSubset = new T[subsets[j].Length + 1];
subsets[j].CopyTo(newSubset, 0);
newSubset[newSubset.Length - 1] = originalArray[i];
subsets.Add(newSubset);
}
}
return subsets;
}
}
This will give you the following results for your inputs of 2,3,5,7.
2=2
3=3
2x3=6
5=5
2x5=10
3x5=15
2x3x5=30
7=7
2x7=14
3x7=21
2x3x7=42
5x7=35
2x5x7=70
3x5x7=105
2x3x5x7=210
This could have been through recursion but this method was probably just as simple. The trick is creating your list of subsets. Once you have that, you simply multiply all of the elements of each subset together.
Related
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;
}
I have a sql list "GetStaff()" that has 9 people in it and when the code runs it splits them in two teams but only displays 4 in each team. I cannot get the 9th member to be displayed in the team.How can I adjust the code to hold odd number of people and not just even in a split team.Any help would be helpful.
public List<Staff[]> CreateTeams(int membersPerTeam)
{
IList<Staff> allUsers = GetStaff();
int teamCount = allUsers.Count / membersPerTeam;
int usersPerTeam = allUsers.Count / 2;
var teams = new List<Staff[]>();
for (int i = 0; i < teamCount; i++)
{
Staff[] team = new Staff[membersPerTeam];
for (int j = 0; j < usersPerTeam ; j++)
{
team[j] = allUsers[i * membersPerTeam + j];
}
teams.Add(team);
}
return teams;
}
I'd use LINQ:
public List<Staff[]> CreateTeams(int membersPerTeam)
{
IList<Staff> allUsers = GetStaff();
int teams = allUsers.Count() / membersPerTeam + allUsers.Count() % membersPerTeam == 0 ? 0 : 1;;
return
allUsers
.Select((x, n) => new { x, n })
.GroupBy(z => z.n % teams)
.Select(zs => zs.Select(z => z.x).ToArray())
.ToList();
}
This simply projects the list to include an n index number and then groups by the modulus of membersPerTeam against that n. Then it removes the index and returns the results.
Based on #Enigmativity's answer and clarifications in comments, I'd suggest a simplyfied version of his solution:
public List<Staff[]> CreateTwoTeams() // No argument => You don't know the total number
{
return
GetStaff() // Get all members
.Select((x, n) => new { x, n }) // add an index
.GroupBy(z => z.n % 2) // Create 2 Groups: Even and Odd
.Select(zs => zs.Select(z => z.x) // For each Group: make an array
.ToArray()) // of the members
.ToList(); // Make a List of those arrays.
}
If you later chose to make the number of teams variable, you can simply introduce an argument and replace the hardcoded "2" by it.
This line is likely to be your problem
int usersPerTeam = allUsers.Count / 2;
When you have an odd number this will lose the decimal part, 9 / 2 = 4 when the result must be an int
Try checking for the odd number, and adding one if it is odd
var userCount = allUsers.Count % 2 = 0 ? allUsers.Count : allUsers.Count + 1
int teamCount = userCount / 2
I'm trying to do the Modified Kaprekar Numbers problem (https://www.hackerrank.com/challenges/kaprekar-numbers) which describes a Kaprekar number by
Here's an explanation from Wikipedia about the ORIGINAL Kaprekar
Number (spot the difference!): In mathematics, a Kaprekar number for a
given base is a non-negative integer, the representation of whose
square in that base can be split into two parts that add up to the
original number again. For instance, 45 is a Kaprekar number, because
45² = 2025 and 20+25 = 45.
and what I don't understand is why 10 and 100 aren't Kaprekar numbers.
10^2 = 1000 and 10 + 00 = 10
Right?
So my solution
// Returns the number represented by the digits
// in the range arr[i], arr[i + 1], ..., arr[j - 1].
// If there are no elements in range, return 0.
static int NumberInRange(int[] arr, int i, int j)
{
int result = 0;
for(; i < j; ++i)
{
result *= 10;
result += arr[i];
}
return result;
}
// Returns true or false depending on whether k
// is a Kaprekar number.
// Example: IsKaprekar(45) = true because 45^2=2025 and 20+25=45
// Example: IsKaprekar(9) = false because the set of the split
// digits of 7^2=49 are {49,0},{4,9} and
// neither of 49+0 or 4+9 equal 7.
static bool IsKaprekar(int k)
{
int square = k * k;
int[] digits = square.ToString().Select(c => (int)Char.GetNumericValue(c)).ToArray();
for(int i = 0; i < digits.Length; ++i)
{
int right = NumberInRange(digits, 0, i);
int left = NumberInRange(digits, i, digits.Length);
if((right + left) == k)
return true;
}
return false;
}
is saying all the Kaprekar numbers between 1 and 100 are
1 9 10 45 55 99 100
whereas the "right" answer is
1 9 45 55 99
In 100+00 the right is 00, which is wrong because in a kaprekar number the right may start with zero (ex: 025) but cannot be entirely 0.
Therefore you can put a condition in the loop that
if(right==0)
return false;
The reason is because 10 x 10 = 100. Then you substring the right part with a length equals d = 2, that is digit count of original value (10), then the left part would be 1.
So l = 1 and r = 00, l + r = 1, that is not equals to 10.
The same for 100. 100 x 100 = 10000. l = 10, r = 000, so l + r = 10 not equal 100.
Here is my solution in JAVA.
static void kaprekarNumbers(int p, int q) {
long[] result = IntStream.rangeClosed(p, q).mapToLong(Long::valueOf)
.filter(v -> {
int d = String.valueOf(v).length();
Long sq = v * v;
String sqSt = sq.toString();
if (sqSt.length() > 1) {
long r = Long.parseLong(sqSt.substring(sqSt.length() - d));
long l = Long.parseLong(sqSt.substring(0, sqSt.length() - d));
return r + l == v;
} else return v == 1;
}).toArray();
if (result.length > 0) {
for (long l : result) {
System.out.print(l + " ");
}
} else {
System.out.println("INVALID RANGE");
}
}
How about something like this.
static bool IsKaprekar(int k)
{
int t;
for (int digits = new String(k).length(); digits > 0; digits--, t *= 10);
long sq = k * k;
long first = sq / t;
long second = sq % t;
return k == first + second;
}
find a number to divide and mod the square with in order to split it. This number should be a factor of 10 based on the number of digits in the original number.
calculate the square.
split the square.
compare the original to the sum of the splits.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a number 6 and now I need to search inside an array of ints if any of the numbers can be added together to get 6.
Example:
1,2,3,5,4
In the above array I can take 1+2+3 which makes 6.
I can also take 4+2 which is 6.
The question is how do I find those individual numbers that can sum up to the number 6.
One possible option is to get a list of all combinations of items in the array, then check which one of those has the sum of your target number.
I found an extension method for getting the combinations here (copied below).
public static IEnumerable<T[]> Combinations<T>(this IList<T> argList, int argSetSize)
{
if (argList == null) throw new ArgumentNullException("argList");
if (argSetSize <= 0) throw new ArgumentException("argSetSize Must be greater than 0", "argSetSize");
return combinationsImpl(argList, 0, argSetSize - 1);
}
private static IEnumerable<T[]> combinationsImpl<T>(IList<T> argList, int argStart, int argIteration, List<int> argIndicies = null)
{
argIndicies = argIndicies ?? new List<int>();
for (int i = argStart; i < argList.Count; i++)
{
argIndicies.Add(i);
if (argIteration > 0)
{
foreach (var array in combinationsImpl(argList, i + 1, argIteration - 1, argIndicies))
{
yield return array;
}
}
else
{
var array = new T[argIndicies.Count];
for (int j = 0; j < argIndicies.Count; j++)
{
array[j] = argList[argIndicies[j]];
}
yield return array;
}
argIndicies.RemoveAt(argIndicies.Count - 1);
}
}
Now you just need to call it with the number of combinations you want in your groups. For example, if you wanted to find groups of 2:
List<int> ints = new List<int>() { 1, 2, 3, 4, 5 };
int target = 6;
var combs2 = ints.Combinations(2)
.Where(x => x.Sum() == target);
This will return 1,5 and 2,4. You can then repeat this up to the maximum number of items you want in a group.
If you want to get all the results at once, make a new extension method that will do the unioning for you:
public static IEnumerable<T[]> AllCombinations<T>(this IList<T> argsList)
{
for (int i = 1; i <= argsList.Count; i++)
{
foreach (var combo in argsList.Combinations(i))
{
yield return combo;
}
}
}
Then you can get all your combinations at once by running
var allCombos = ints.AllCombinations()
.Where(x => x.Sum() == target);
So for your example, it will return 1,5, 2,4, and 1,2,3 in one collection.
If you want to know whether (and discover these numbers) two numbers sum to X it's an easy task and you can do it O(n) on average.
HashSet<int> numbers = new HashSet<int>(yourNumberArray);
foreach(int number in numbers)
if(numbers.Contains(x-number))
Console.WriteLine(number + " " + "numbers[x-number]");
However when you want to know if x1,x2,...,xk numbers sum to X it's NP-complete problem and no polynominal bounded solution is known (also it is not known does such solution exists). If number of items in your set is small (about ~20-30) you can brute-force your result by enumerating all subsets.
for (int i=1; i< (1 << setSize); ++i)
{
check does number in current set sum to X by bitwise operations on i
(treat number binary representation as information about set
(binary one means item is in set, zero means item is not in set)
}
You can also reduce this problem to knapsack problem and get pseudo-polynominal time, however maximum value in set shouldn't be big. For more information check: http://www.geeksforgeeks.org/dynamic-programming-subset-sum-problem/
You can find all combinations which results 6 using Lipski's algorithm like this:
static List<List<int>> FindCombinations(int x)
{
var combinations = new List<List<int>>();
var P = new int[10];
var R = new int[10];
combinations.Add(Enumerable.Repeat(1,x)); // first combination
P[1] = x;
R[1] = 1;
int d = 1, b, sum;
while (P[1] > 1)
{
sum = 0;
if (P[d] == 1)
{
sum = sum + R[d];
d = d - 1;
}
sum = sum + P[d];
R[d] = R[d] - 1;
b = P[d] - 1;
if (R[d] > 0) d++;
P[d] = b;
R[d] = sum/b;
b = sum%b;
if (b != 0)
{
d++;
P[d] = b;
R[d] = 1;
}
List<int> temp = new List<int>();
for (int i = 1; i <= d; i++)
temp = temp.Concat(Enumerable.Repeat(P[i], R[i])).ToList();
combinations.Add(temp);
}
return combinations;
}
Then all you need to is compare each sequence with your numbers:
var combinations = FindCombinations(6);
var numbers = new List<int> {1, 2, 3, 5, 4,6};
var result =
combinations.Where(x => x.Intersect(numbers).Count() == x.Count)
.Select(x => x.Intersect(numbers))
.ToList();
Here is the result in LINQPad:
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.