LINQ equivalent of F# List.partition - linq

Using LINQ, how do you partition an IEnumerable in a way equivalent to F#'s List.parition function? The result should be the source sequence partitioned into two sequences based the predicate, with the predicate evaluated once per source item.

Enumerable.ToLookup comes close.
var l = new int[]{1,2,3,4,5};
var split = l.ToLookup( i => i > 2);
var a = split[true]; // 3,4,5
var b = split[false]; // 1,2
It's not too hard to wrap this in a function.
public static (IEnumerable<TSource> Yeses, IEnumerable<TSource> Nos) Partition<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
//Null handling?
var s = source.ToLookup(i => predicate(i));
return (s[true], s[false]);
}
public static void Main(string[] args)
{
var l = new int[] { 1,2,3,4,5 };
var s = Partition(l, i => { Console.WriteLine($"Called: {i}"); return i > 2;});
Console.WriteLine(string.Join(",", s.Yeses));
Console.WriteLine(string.Join(",", s.Nos));
}
Called: 1
Called: 2
Called: 3
Called: 4
Called: 5
3,4,5
1,2

I would suggest this way:
F# (test-case)
let list1 = [ 1 .. 10 ]
let listEven, listOdd = List.partition (fun elem -> elem % 2 = 0) list1
printfn "Evens: %A\nOdds: %A" listEven listOdd
/* Result:
Evens: [2; 4; 6; 8; 10]
Odds: [1; 3; 5; 7; 9]
*/
C# (test-case)
var list1 = Enumerable.Range(1, 10);
var (listEven, listOdd) = list1
.GroupBy(key => key % 2 == 0)
.Aggregate(
(part1: Enumerable.Empty<int>(), part2: Enumerable.Empty<int>()),
(accumulator, value) => {
if (value.Key)
{
accumulator.part1 = value.ToArray();
}
else
{
accumulator.part2 = value.ToArray();
}
return accumulator;
});
Console.WriteLine($"Evens: [{string.Join("; ", listEven)}]\nOdds: [{string.Join("; ", listOdd)}]");
/* Result:
Evens: [2; 4; 6; 8; 10]
Odds: [1; 3; 5; 7; 9]
*/
To reuse&generalize this method define the extension-method:
public static class EnumerableExtensions
{
public static (T[] part1, T[] part2) Partition<T>(this IEnumerable<T> self, Func<T, bool> predicate)
{
return self
.GroupBy(predicate)
.Aggregate(
(part1: Array.Empty<T>(), part2: Array.Empty<T>()),
(accumulator, value) => {
if (value.Key)
{
accumulator.part1 = value.ToArray();
}
else
{
accumulator.part2 = value.ToArray();
}
return accumulator;
});
}
}
Use it like this:
var list1 = Enumerable.Range(1, 10);
var (listEven, listOdd) = list1.Partition(v => v % 2 == 0);
Console.WriteLine($"Evens: [{string.Join("; ", listEven)}]\nOdds: [{string.Join("; ", listOdd)}]");
/* Result:
Evens: [2; 4; 6; 8; 10]
Odds: [1; 3; 5; 7; 9]
*/
var str = "aAbbBcCddD";
var (lowers, uppers) = str.Partition(v => char.IsLower(v));
Console.WriteLine($"Lowers: [{string.Join("; ", lowers)}]\nUppers: [{string.Join("; ", uppers)}]");
/* Result:
Lowers: [a; b; b; c; d; d]
Uppers: [A; B; C; D]
*/

Related

Suggestion to write a number as a sum of three numbers where each number is at least two

I'm trying to find all possible combinations to write a number as a sum of three numbers, where each number is at least 2.
So basically for 6 it would be like:
2 2 2
For 7 it would be:
2 2 3 or 2 3 2 or 3 2 2
I was wondering if there's a better approach to this than running 3 loops.
EDIT:
public class Problem {
public static void main(String args[]) {
int N = 7, n1, n2, n3;
for (n1 = 2; n1 <= N; n1++) {
for (n2 = 2; n2 <= N; n2++) {
for (n3 = 2; n3 <= N; n3++) {
if ( (n1+n2+n3)==N ) {
System.out.println(n1 + " " + n2 + " " + n3);
}
}
}
}
}
}
This solution works, but I was thinking if there's another approach to this.
You're looking to partition an integer n into k parts, where each part has a minimum value min. The classic approach here would be to use recursion.
Initially we create an array to hold the parts, initialize them to min and remove k*min from n to get the remainder.
static List<int[]> partitions(int n, int k, int min)
{
int[] parts = new int [k];
Arrays.fill(parts, min);
int rem = n - k*min;
List<int[]> results = new ArrayList<>();
partition(results, parts, rem);
return results;
}
We now use a recursive method to explore adding 1 to each of the parts in turn. If the remainder reaches 0 we have a solution and add the current solution to the results.
static void partition(List<int[]> results, int[] parts, int rem)
{
if(rem <= 0)
{
if(rem == 0) results.add(parts.clone());
return;
}
for(int i=0; i<parts.length; i++)
{
parts[i] += 1;
partition(results, parts, rem-1);
parts[i] -= 1;
}
}
Test:
public static void main(String[] args)
{
for(int[] res : partitions(7, 3, 2))
System.out.println(Arrays.toString(res));
}
Output:
[3, 2, 2]
[2, 3, 2]
[2, 2, 3]
it is my suggestion
create a class to model each answer of equation here we create a static inner class to model each answer:
public static class Answer{
private int a;
private int b;
private int c;
public Answer(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
public int getA() {
return a;
}
public int getB() {
return b;
}
public int getC() {
return c;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Answer answer = (Answer) o;
return a == answer.a &&
b == answer.b &&
c == answer.c;
}
#Override
public int hashCode() {
return Objects.hash(a, b, c);
}
#Override
public String toString() {
return "Answer{" +
"a=" + a +
", b=" + b +
", c=" + c +
'}';
}
}
then a recursive algorithm to produce results:
// don't call this method directly only combination method must call it
private Set<Answer> combinationHelper(int n){
Set<Answer> results = new HashSet<>();
if(n < 0)
return results;
if(n == 0) {
results.add(new Answer(0, 0, 0));
return results;
}
Set<Answer> remain = combinationHelper(n - 1);
remain.forEach(element -> {
int a = element.getA();
int b = element.getB();
int c = element.getC();
results.add(new Answer(a + 1, b, c));
results.add(new Answer(a, b + 1, c));
results.add(new Answer(a, b, c + 1));
});
return results;
}
public Set<Answer> combination(int n){
Set<Answer> results = combinationHelper(n - 6);
return results.stream()
.map(a -> new Answer(a.getA() + 2, a.getB() + 2, a.getC() + 2))
.collect(Collectors.toSet());
}
then call it like this:
System.out.println(new Comb().combination(6));
System.out.println(new Comb().combination(7));
which produces results:
[Answer{a=2, b=2, c=2}]
[Answer{a=2, b=3, c=2}, Answer{a=3, b=2, c=2}, Answer{a=2, b=2, c=3}]
if you don't like the idea of adding another model class to your application you can easily use arrays instead
non-recursive approach:
public List<String> combination(int n){
List<String> result = new ArrayList<>();
if(n < 6)
return result;
BitSet bits = new BitSet(n - 6);
bits.set(0, n - 6);
IntStream
.range(0, n - 5)
.forEach(i ->
IntStream.range(i, n - 5).forEach(j ->
result.add(String.format("%s %d %d %d %s", "{", bits.get(0, i).length() + 2, bits.get(i, j).length() + 2, bits.get(j, n).length() + 2, "}"))));
return result;
}
results for non-recursive approach:
for input 7:
[{ 2 2 3 }, { 2 3 2 }, { 3 2 2 }]
for input 6:
[{ 2 2 2 }]

Easy way to sort default array in Vala

I tried it like this, but it doesn't work. And I think it's too complicated a way to sort an array. I need something like System.Array.Sort () of C#
int[] data = { 3, 9, 2, 7, 5 };
var arr = new Array<int> ();
arr.append_vals (data,data.length);
arr.sort((a, b) => {
return (int) (a > b) - (int) (a < b);
});
for (int i=0;i<arr.length;i++) {
print(#"$(arr.index(i))\t");
}
also tried that, the array is still not sorted.
using Posix;
int cmpfunc(ref int a, ref int b) {
return (int) (a > b) - (int) (a < b);
}
void main() {
int[] data = { 3, 9, 2, 7, 5 };
Posix.qsort (data, data.length, sizeof(string), (Posix.compar_fn_t) cmpfunc);
foreach (int st in data) {
print(#"$st\t");
}
}
The Posix.qsort function needs to know the size of each element in the array, sizeof(int), but you're giving it the size of a different type, sizeof(string).

Random generator Rand9() using Rand3()

How can I generate a number between 1 and 9 using a function which generate a number between 1 and 3? The probability to obtain any number between 1 and 9 must be the same, so rand3()+rand3()+rand3() is not a good solution.
Try cartesian-like product:
Rand9() = 3 * (Rand3() - 1) + Rand3()
With 3 * (Rand3() - 1) you make sub-intervals 1-3, 4-6 and 7-9 equally likely. With + Rand3() you will then choose equally on that sub-interval.
Written as a product:
3 * (Rand3() - 1) + Rand3() -> {1, 4, 7} X {+1,+2,+3} -> {1,2,3,4,5,6,7,8,9}
The main idea of the solution is to build 3*3 matrix.
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
function init() {
const rand3 = generateMathRandom(3);
let randFunc = rand3;
const start = 9;
const end = 10;
let i = start;
console.time('---start');
while (i < end) {
randFunc = generateRandom(i, 3, rand3);
healthCheck(i, randFunc);
i++;
}
console.timeEnd('---start');
i = start;
console.time('---start-math');
while (i < end) {
randFunc = generateMathRandom(i);
healthCheck(i, randFunc);
i++;
}
console.timeEnd('---start-math');
}
function generateMathRandom(range) {
return function () {
return Math.floor(Math.random() * range);
}
}
// range - target random range number : e.g 9
// lowerRange - base random range number : e.g 3
// func - function which generate random with the range of lowerRange : e.g rand3
function generateRandom(range, lowerRange, func) {
return function () {
const results = [];
let times = 1;
let matRange = lowerRange;
let mat = Math.sqrt(range);
while(mat > lowerRange) {
mat = Math.sqrt(mat);
times ++;
matRange *= lowerRange;
}
const noneStart = Math.floor(matRange * matRange / range) * range;
for (let i = 0; i < matRange; i++) {
results.push([]);
for (let j = 0; j < matRange; j++) {
const num = i * matRange + j;
if (num < noneStart)
results[i].push(num % range);
else
results[i].push(-1);
}
}
while (true) {
const row = new Array(times).fill(1).map(n => func()).reduce((a, c) => a * lowerRange + c, 0);
const col = new Array(times).fill(1).map(n => func()).reduce((a, c) => a * lowerRange + c, 0);
if (!results[row]) {
debugger;
}
if (results[row][col] == undefined) {
debugger;
}
if (results[row][col] === -1) continue;
return results[row][col];
}
}
}
function healthCheck(range, func = null, count = 100000) {
const funcToCheck = func || rand[range] || null;
if (!funcToCheck) {
console.log('Function is not provided');
return;
}
const health = new Array(range).fill(0);
const checkCount = count - count % range; // To do correct check.
for (let i = 0; i < checkCount; i++) {
health[funcToCheck()]++;
}
const result = health.map((cnt, index) => ({
_value: index,
rate: (cnt / checkCount * 100).toFixed(5)
}));
// console.log('Random result:', result);
let minRate = 100, maxRate = 0;
for (let i = 0; i < range; i++) {
minRate = Math.min(Number(result[i].rate), minRate);
maxRate = Math.max(Number(result[i].rate), maxRate);
}
console.log('Random health<' + range + '>: ' + healthOutput(range, maxRate - minRate));
}
function healthOutput(range, rangeOffset) {
const healthThreshold = 2; // It should be lower for the best Alghorithms
const threshold = healthThreshold;
if (rangeOffset < threshold * 0.2) {
return 'The Super! -> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 0.5) {
return 'The Best! --> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 1) {
return 'Good work! -> ' + rangeOffset.toFixed(5);
} else if (rangeOffset < threshold * 2) {
return 'Not bad! ---> ' + rangeOffset.toFixed(5);
}
return 'Worst! -----> ' + rangeOffset.toFixed(5);
}
init();

Interview - Oracle

In a game the only scores which can be made are 2,3,4,5,6,7,8 and they can be made any number of times
What are the total number of combinations in which the team can play and the score of 50 can be achieved by the team.
example 8,8,8,8,8,8,2 is valid 8,8,8,8,8,4,4,2 is also valid. etc...
The problem can be solved with dynamic programming, with 2 parameters:
i - the index up to which we have considered
s - the total score.
f(i, s) will contain the total number of ways to achieve score s.
Let score[] be the list of unique positive scores that can be made.
The formulation for the DP solution:
f(0, s) = 1, for all s divisible to score[0]
f(0, s) = 0, otherwise
f(i + 1, s) = Sum [for k = 0 .. floor(s/score[i + 1])] f(i, s - score[i + 1] * k)
This looks like a coin change problem. I wrote some Python code for it a while back.
Edited Solution:
from collections import defaultdict
my_dicto = defaultdict(dict)
def row_analysis(v, my_dicto, coins):
temp = 0
for coin in coins:
if v >= coin:
if v - coin == 0: # changed from if v - coin in (0, 1):
temp += 1
my_dicto[coin][v] = temp
else:
temp += my_dicto[coin][v - coin]
my_dicto[coin][v] = temp
else:
my_dicto[coin][v] = temp
return my_dicto
def get_combs(coins, value):
'''
Returns answer for coin change type problems.
Coins are assumed to be sorted.
Example:
>>> get_combs([1,2,3,5,10,15,20], 50)
2955
'''
dicto = defaultdict(dict)
for v in xrange(value + 1):
dicto = row_analysis(v, dicto, coins)
return dicto[coins[-1]][value]
In your case:
>>> get_combs([2,3,4,5,6,7,8], 50)
3095
It is like visit a 7-branches decision tree.
The code is:
class WinScore{
static final int totalScore=50;
static final int[] list={2,3,4,5,6,7,8};
public static int methodNum=0;
static void visitTree( int achieved , int index){
if (achieved >= totalScore ){
return;
}
for ( int i=index; i< list.length; i++ ){
if ( achieved + list[i] == totalScore ) {
methodNum++;
}else if ( achieved + list[i] < totalScore ){
visitTree( achieved + list[i], i );
}
}
}
public static void main( String[] args ){
visitTree(0, 0);
System.out.println("number of methods are:" + methodNum );
}
}
output:
number of methods are:3095
Just stumbled on this question - here's a c# variation which allows you to explore the different combinations:
static class SlotIterator
{
public static IEnumerable<string> Discover(this int[] set, int maxScore)
{
var st = new Stack<Slot>();
var combinations = 0;
set = set.OrderBy(c => c).ToArray();
st.Push(new Slot(0, 0, set.Length));
while (st.Count > 0)
{
var m = st.Pop();
for (var i = m.Index; i < set.Length; i++)
{
if (m.Counter + set[i] < maxScore)
{
st.Push(m.Clone(m.Counter + set[i], i));
}
else if (m.Counter + set[i] == maxScore)
{
m.SetSlot(i);
yield return m.Slots.PrintSlots(set, ++combinations, maxScore);
}
}
}
}
public static string PrintSlots(this int[] slots, int[] set, int numVariation, int maxScore)
{
var sb = new StringBuilder();
var accumulate = 0;
for (var j = 0; j < slots.Length; j++)
{
if (slots[j] <= 0)
{
continue;
}
var plus = "+";
for (var k = 0; k < slots[j]; k++)
{
accumulate += set[j];
if (accumulate == maxScore) plus = "";
sb.AppendFormat("{0}{1}", set[j], plus);
}
}
sb.AppendFormat("={0} - Variation nr. {1}", accumulate, numVariation);
return sb.ToString();
}
}
public class Slot
{
public Slot(int counter, int index, int countSlots)
{
this.Slots = new int[countSlots];
this.Counter = counter;
this.Index = index;
}
public void SetSlot(int index)
{
this.Slots[index]++;
}
public Slot Clone(int newval, int index)
{
var s = new Slot(newval, index, this.Slots.Length);
this.Slots.CopyTo(s.Slots, 0);
s.SetSlot(index);
return s;
}
public int[] Slots { get; private set; }
public int Counter { get; set; }
public int Index { get; set; }
}
Example:
static void Main(string[] args)
{
using (var sw = new StreamWriter(#"c:\test\comb50.txt"))
{
foreach (var s in new[] { 2, 3, 4, 5, 6, 7, 8 }.Discover(50))
{
sw.WriteLine(s);
}
}
}
Yields 3095 combinations.

Generate 5 different non repeatable random numbers in unityscript

please tell me how to generate 5 different non repeatable random number between 1,20 in javascript for unity3d
this the code i have written.. this works 1st 3 times but crashes the last time. please tell me how i can improvise this i have taken numbers in an array to print them on screen n n checked for their repeatability. this works ly 3 times.. for 4th time unity crashes. i know the reason dunno how solve it.. i think it is because it is not able to detect the remaining numbers of the array. Please tell me where i have gone wrong.. i'm new to unity.
var temp : int = 0;
var array = new Array();
var count : int = 0;
var n : int = 0;
var b : int = 0;
var num = new Array();
var num1 : int = 0;
var num2 : int = 0;
var num3 : int = 0;
var num4 : int = 0;
var num5 : int = 0;
var number1 : GUIText;
var number2 : GUIText;
var number3 : GUIText;
var number4 : GUIText;
var number5 : GUIText;
function Start () {
if((temp == 0) || (temp ==20))
{
//for(a=1;a<=20;a++)
//{
temp=0;
array[1]=1;
array[2]=2;
array[3]=3;
array[4]=4;
array[5]=5;
array[6]=6;
array[7]=7;
array[8]=8;
array[9]=9;
array[10]=10;
array[11]=11;
array[12]=12;
array[13]=13;
array[14]=14;
array[15]=15;
array[16]=16;
array[17]=17;
array[18]=18;
array[19]=19;
array[20]=20;
//array[1]=a;
//}
}
}
function OnGUI ()
{
if (GUI.Button (Rect (100,200,100,100), "Click Me"))
{
count=0;
//print(count);
genrandom() ;
for(a=1;a<=6;a++)
{
//print("A is"+a);
genrandom() ;
temp++;
count=count+1;
//print("Count is :"+count);
if(count>=6){count = 0;}
}
}
}
function genrandom()
{
//temp++;
//print(temp);
if(count<=5)
{
n = Random.Range(1,20);
//print("N is"+n);
if(array[n]!=0)
{
if(count==1)
{
print("Count is 1");
num1 = array[n];
array[n]=0;
number1.text = ""+num1;
//count++;
}
if(count==2)
{
print("Count is 2");
num2 = array[n];
array[n]=0;
number2.text = ""+num2;
//count++;
}
if(count==3)
{
print("Count is 3");
num3 = array[n];
array[n]=0;
number3.text = ""+num3;
//count++;
}
if(count==4)
{
print("Count is 4");
num4 = array[n];
array[n]=0;
number4.text = ""+num4;
//count++;
}
if(count==5)
{
print("Inside count= 5");
num5 = array[n];
array[n]=0;
number5.text = ""+num5;
//count++;
}
}
else
{
genrandom();
}
}
}
One way to go about this would be to create the array of possible values, shuffle it, and look at the first five elements:
http://en.wikipedia.org/wiki/Fisher-Yates
http://jsfromhell.com/array/shuffle
Example: http://jsfiddle.net/Q9ZAZ/

Resources