I have a list of values, say A, B and C. I want to join it with itself to get all distinct combinations considering a value can't join itself and that A-B is the same as B-A
The end result should be
A-B, A-C, B-C
and not a full cross product
A-A, A-B, A-C, B-A, B-B, B-C, C-A, C-B, C-C
In traditional code, I came up with the following
var myList = new List<string> { "A", "B", "C" };
for(var i=0; i < myList.Count; i++)
for (var j=i+1; j < myList.Count; j++)
//Do Something
Is there any LINQ equivalent? I'm mainly seeking a more meaningful and human readable implementation.
I found one way to do it in LInQ but I don't think it qualifies as more meaningful nor readable and mostly, from a performance perspective, it is 3 to 7 (from the first test run I did with only A, B, C in a fixed List) times slower.
from item1 in myList
from item2 in myList.SkipWhile(x => x != item1).Skip(1)
select (item1, item2)
I first thought the main reason the performance was that bad with the LInQ versions was becaus it still ran a full cross product but my simplistic benchmark seems to disagree.
Count
V1
V2
Ratio
V1/item
V2/item
V1/item^2
V2/item^2
1
10
125
455
3,640
12,500
45,500
1,250
4,550
2
10
124
440
3,548
12,400
44,000
1,240
4,400
3
30
976
3034
3,109
32,533
101,133
1,084
3,371
4
30
975
3023
3,101
32,500
100,767
1,083
3,359
5
50
2702
8088
2,993
54,040
161,760
1,081
3,235
6
50
2763
8155
2,952
55,260
163,100
1,105
3,262
7
70
5393
15708
2,913
77,043
224,400
1,101
3,206
8
70
5416
15740
2,906
77,371
224,857
1,105
3,212
9
90
8993
25908
2,881
99,922
287,867
1,110
3,199
10
90
8983
25869
2,880
99,811
287,433
1,109
3,194
Benchmark code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Benchmarks
{
class Program
{
static void Main(string[] args)
{
for (var i = 1; i <= 10; i+=2)
{
CrossProduct(i, Enumerable.Range(1,10*i).Select(x => x.ToString()).ToList());
}
_ = Console.Read();
}
private static void CrossProduct(int iterations, IList<string> data)
{
var v1 = CrossProductV1(data);
var v2 = CrossProductV2(data);
Console.WriteLine($"{iterations} | DataCount: {data.Count}\t| V1:{v1}* | V2:{v2}");
v2 = CrossProductV2(data);
v1 = CrossProductV1(data);
Console.WriteLine($"{iterations+1} | DataCount: {data.Count}\t| V1:{v1} | V2:{v2}*");
}
private static long CrossProductV1(IList<string> data)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
for (var repeatIndex = 0; repeatIndex < 100000; repeatIndex++)
{
List<object> result = new List<object>();
for (var i = 0; i < data.Count; i++)
for (var j = i + 1; j < data.Count; j++)
result.Add((data[i], data[j]));
}
return sw.ElapsedMilliseconds;
}
private static long CrossProductV2(IList<string> data)
{
var sw = System.Diagnostics.Stopwatch.StartNew();
for (var repeatIndex = 0; repeatIndex < 100000; repeatIndex++)
{
List<object> result = null;
result = (from item1 in data
from item2 in data.SkipWhile(x => x != item1).Skip(1)
select (object)(item1, item2)).ToList();
}
return sw.ElapsedMilliseconds;
}
}
}
Related
There are 4 friends A,B,C,D each having some amount of money which they share among themselves everyday until it could not be shared equally, For example A has 15$ , it shares 5,5,5 to B,C,D similarly B = 9$ shares 3$,3$,3$ to other three, and C with 21$ and D with 12$ does the same, so now A has 14, B has 16 and C has 12 and D has 15.
Next Day they will again share their updated money in a same manner. I have to count the days until they can share it equally,enter image description here and if amount can be share forever return -1. for ex: When All 4 has 3$.
However i was not able to pass all the test cases due to runtime error and stackoverflow exception.
My code:
class Program {
public int Friends(int a,int b, int c, int d, int count)
{
int m = b/3 + c/3 + d/3;
int n = c/3 + d/3 + a/3;
int o = d/3 + a/3 + b/3;
int p = a/3 + b/3 + c/3;
a=m;
b=n;
c=o;
d=p;
count +=1;
count = Friends(a,b,c,d,count);
return count;
}
static void Main(){
int count =0;
Program p = new Program();
int a = p.Friends(3,3,3,3, count);
System.Console.WriteLine(a);
}
}
You shouldn't call the function main() from the same class, or the function Friend() will be called recursively, creating new Program class instance, and so call main() again and again.
I need to write matrices of different dimensions in OPL CPLEX.
Currently, I wrote this for loop :
{int} row=...;
{int} col=...;
int y[row][col];
execute
{
for (var i=1; i<=row.size; i+=10){
for (var j in col){
y[i][j]=i;
}
}
writeln("y= ",y,
"/ row = ", row.size,
"/ col = ", col.size,
"/ time = ", cplex.getCplexTime());
}
Currently, in the scripting log, I obtain as a solution all the matrices (from 1x2 to 100x2).
I would like to compute (and print) only the matrices 1x2, 10x2, 20x2, ..., 90x2 and 100x2.
Essentially I would like to print a matrix every 10 rows (so in total 11 matrices and not 100).
I tried to multiply the row.size per 10 (or divide it per 10 when the row value is 100).
How can I do that ?
UPDATE :
main.mod :
{int} set1={};
{int} set2={};
int ar[1..100][1..100];
main {
var source = new IloOplModelSource("sub.mod");
var cplex = new IloCplex();
var def = new IloOplModelDefinition(source);
for(var i=1;i<=30;i++) if (i % 10 == 0) {
for (var j=1; j<=30; j++) if (j % 10 == 0) {
var opl = new IloOplModel(def,cplex);
var data2= new IloOplDataElements();
data2.row=thisOplModel.set1;
data2.row.add(i);
data2.col=thisOplModel.set2;
data2.col.add(j);
}
opl.addDataSource(data2);
opl.generate();
}
if (cplex.solve()) {
writeln("Solution = " + cplex.getObjValue(),
"/ time = ", cplex.getCplexTime());
} else {
writeln("No solution");
}
data2.end();
opl.end();
}
sub.mod :
{int} row=...;
{int} col=...;
int y[row][col];
execute {
for (var i in row) {
for (var j in col) {
y[i][j]=i;
}
}
writeln("y= ",y,
// " / i= ", i,
// "/ row = ", row,
"/ col = ", col,
"/ time = ", cplex.getCplexTime());
}
dvar float x;
maximize x;
subject to {
x<=sum(i in row, j in col) y[i][j];
}
execute
{
writeln("x=",x);
}
Now, I obtain the right values in row = {10, 20, 30} and col = {10, 20, 30} in the main.mod.
In sub.mod row and col are sets. I need to use those values as matrices dimensions. So the first matrix is 10x10, the second 20x20 etc..
How can I access the values inside the set so that I can create those matrices ?
Sorry for the multiple questions but I am really new to CPLEX.
you could use modulo
range r=1..100;
execute
{
for(var i in r) if (i % 10==0) writeln(i);
}
gives
10
20
30
40
50
60
70
80
90
100
You can slightly rewrite your sub.mod to get this going:
{int} rowSet = ...;
{int} colSet = ...;
range row = 1..last(rowSet);
range col = 1..last(colSet);
int y[row][col];
execute {
for (var i in row) {
for (var j in col) {
y[i][j] = i;
}
}
writeln(y);
}
The last function will return the last element from the respective set. So in the first iteration you get 10, in the second 20 and in the third 30. Then row and col are constructed as range with the desired number of elements. These can then be used to initialize the array.
Note that in main.mod you must replace data2.row by data2.rowSet and data2.col by data2.colSet.
There is a school in a village. It has N classes. One fine day, someone donated B blue berry cheese cakes to schools. Now you need to divide these cakes such that:
Each class gets at least 1 cake.
Each class will share the cake(s) among students.
Your aim is to minimize the maximum number of students per cake in any class.
input
contains two space separated integers N and B denoting the number of classes and total number of blue berry cheese cakes, respectively.
Next N lines contain number of students in each class.
Output
For each test case, output the maximum number of students who will share a cake.
Constraints
2 <= N <= 5*10^5
N <= B <= 2*10^6 1 <= number of students in ith class <= 5*10^6
Sample Input - 1 1 2 35 Sample Output - 1 18 Sample Input - 2 2 7 20 50 Sample Output - 2 10
Apply binary search to find minimum number of students/cake.
Take lower limit 'l' as 1 and upper limit 'u' as max number of students in any given class.
Let 'mid' represents current students/cake where mid=(l+u)/2, then,
calculate required number of cakes 'req' for each mid value,
if req<=total number of cakes u=mid-1 else l=mid+1.
Apply the binary search.
Handle the case when n>b separately.
Link to my C++ code for this problem : https://ideone.com/zsTHC5
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
ll n,b;cin>>n>>b;
ll arr[n],ans=0;
for(ll i=0;i<n;i++){cin>>arr[i];ans=max(ans,arr[i]);}
if(n>b)cout<<"-1";
else if(n==b)cout<<ans;
else // binary search to find minimum students/cake
{
ll l=1,r=ans,mid; // mid represents current number of students/cake
while(l<=r)
{
mid=(l+r)/2;
ll ct=0;
for(ll i=0;i<n;i++)
{
ct+=(arr[i]+mid-1)/mid;
}
if(ct<=b)
{
ans=min(ans,mid);
r=mid-1;
}
else
l=mid+1;
}
cout<<ans;
}
return 0;
}
I agree with smartsn123.The solution is pretty simple ,initialize the max heap with each class with one cake and then start distributing cakes one by one.Here following the java implementation of the solution.
import java.util.*;
class Node{
private int nStu ;
private int nCake;
public Node(int nStu , int nCake ){
this.nStu = nStu;
this.nCake = nCake;
}
public int getnStu(){
return nStu;
}
public int getnCake(){
return nCake;
}
public void addCake(){
nCake++;
}
}
class CheeseCake{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int B = sc.nextInt();
int[] arr = new int[N];
int ext = B - N ;
MyComparator mc = new MyComparator();
PriorityQueue<Node> queue = new PriorityQueue<>(mc);
for(int i = 0 ; i < N ; i++){
//arr[i] = sc.nextInt();
int temp = sc.nextInt();
Node newNode = new Node(temp , 1);
queue.add(newNode);
}
while(ext != 0){
Node new1 = queue.poll();
new1.addCake();
queue.add(new1);
ext--;
}
Node newNode1 = queue.poll();
int fStu = newNode1.getnStu();
int fCake = newNode1.getnCake();
System.out.println((fStu+1)/2);
}
}
class MyComparator implements Comparator<Node>{
#Override
public int compare(Node n1 , Node n2){
/*arranging based on the students per cakes*/
double avg1 = n1.getnStu() / n1.getnCake();
double avg2 = n2.getnStu() / n2.getnCake();
if(avg1 > avg2){
return -1;
}
if(avg1 < avg2){
return 1;
}
return 0;
}
}
Basically I need to sort arrays of structs by value from highest to lowest.
I must read from file into structure and then sort it.
Initial information:
6
m k 250
f k 280
m p 240
f p 290
m s 63
f s 45
My attempt: (sorting part might be incorrect)
using namespace std;
struct clothes
{
char gender;
char type;
int price;
};
int main()
{
ifstream file("duomenys.txt");
int amount;
int end;
file >> amount;
end = amount;
clothes robe[amount];
for(int x = 0; x<amount; x++)
{
file >> robe[x].gender >> robe[x].type >> robe[x].price;
}
for(int x = amount - 1; x>0; x--)
{
for(int i = 0; i < end; i++)
{
if(robe[i].price > robe[i+1].price)
{
???
}
}
end--;
}
return 0;
}
I'm pretty new in programming so please keep your answer as beginner-friendly as possible as I don't know much.
How do I swap information between struct robe[0] and robe[1] and sort them after checking if price is higher ?
#Beta
So I came up with something that worked, I declared additional struct which I used for holding values while swapping, and then swapped each value (gender, type, price) seperately into holder seperately.
robeH.genderH = robe[i].gender;
robe[i].gender = robe[i+1].gender;
robe[i+1].gender = robeH.genderH;
robeH.typeH = robe[i].type;
robe[i].type = robe[i+1].type;
robe[i+1].type = robeH.typeH;
robeH.priceH = robe[i].price;
robe[i].price = robe[i+1].price;
robe[i+1].price = robeH.priceH;
Thanks for help
P.S. Is it good practice to do it like I did or is there better way
I'm trying to put my first steps into Scala, and to practice I took a look at the google code jam storecredit excersize. I tried it in java first, which went well enough, and now I'm trying to port it to Scala. Now with the java collections framework, I could try to do a straight syntax conversion, but I'd end up writing java in scala, and that kind of defeats the purpose. In my Java implementation, I have a PriorityQueue that I empty into a Deque, and pop the ends off untill we have bingo. This all uses mutable collections, which give me the feeling is very 'un-scala'. What I think would be a more functional approach is to construct a datastructure that can be traversed both from highest to lowest, and from lowest to highest. Am I on the right path? Are there any suitable datastructures supplied in the Scala libraries, or should I roll my own here?
EDIT: full code of the much simpler version in Java. It should run in O(max(credit,inputchars)) and has become:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class StoreCredit {
private static BufferedReader in;
public static void main(String[] args) {
in = new BufferedReader(new InputStreamReader(System.in));
try {
int numCases = Integer.parseInt(in.readLine());
for (int i = 0; i < numCases; i++) {
solveCase(i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void solveCase(int casenum) throws NumberFormatException,
IOException {
int credit = Integer.parseInt(in.readLine());
int numItems = Integer.parseInt(in.readLine());
int itemnumber = 0;
int[] item_numbers_by_price = new int[credit];
Arrays.fill(item_numbers_by_price, -1); // makes this O(max(credit,
// items)) instead of O(items)
int[] read_prices = readItems();
while (itemnumber < numItems) {
int next_price = read_prices[itemnumber];
if (next_price <= credit) {
if (item_numbers_by_price[credit - next_price] >= 0) {
// Bingo! DinoDNA!
printResult(new int[] {
item_numbers_by_price[credit - next_price],
itemnumber }, casenum);
break;
}
item_numbers_by_price[next_price] = itemnumber;
}
itemnumber++;
}
}
private static int[] readItems() throws IOException {
String line = in.readLine();
String[] items = line.split(" "); // uh-oh, now it's O(max(credit,
// inputchars))
int[] result = new int[items.length];
for (int i = 0; i < items.length; i++) {
result[i] = Integer.parseInt(items[i]);
}
return result;
}
private static void printResult(int[] result, int casenum) {
int one;
int two;
if (result[0] > result[1]) {
one = result[1];
two = result[0];
} else {
one = result[0];
two = result[1];
}
one++;
two++;
System.out.println(String.format("Case #%d: %d %d", casenum + 1, one,
two));
}
}
I'm wondering what you are trying to accomplish using sophisticated data structures such as PriorityQueue and Deque for a problem such as this. It can be solved with a pair of nested loops:
for {
i <- 2 to I
j <- 1 until i
if i != j && P(i-1) + P(j - 1) == C
} println("Case #%d: %d %d" format (n, j, i))
Worse than linear, better than quadratic. Since the items are not sorted, and sorting them would require O(nlogn), you can't do much better than this -- as far as I can see.
Actually, having said all that, I now have figured a way to do it in linear time. The trick is that, for every number p you find, you know what its complement is: C - p. I expect there are a few ways to explore that -- I have so far thought of two.
One way is to build a map with O(n) characteristics, such as a bitmap or a hash map. For each element, make it point to its index. One then only has to find an element for which its complement also has an entry in the map. Trivially, this could be as easily as this:
val PM = P.zipWithIndex.toMap
val (p, i) = PM find { case (p, i) => PM isDefinedAt C - p }
val j = PM(C - p)
However, that won't work if the number is equal to its complement. In other words, if there are two p such that p + p == C. There are quite a few such cases in the examples. One could then test for that condition, and then just use indexOf and lastIndexOf -- except that it is possible that there is only one p such that p + p == C, in which case that wouldn't be the answer either.
So I ended with something more complex, that tests the existence of the complement at the same time the map is being built. Here's the full solution:
import scala.io.Source
object StoreCredit3 extends App {
val source = if (args.size > 0) Source fromFile args(0) else Source.stdin
val input = source getLines ()
val N = input.next.toInt
1 to N foreach { n =>
val C = input.next.toInt
val I = input.next.toInt
val Ps = input.next split ' ' map (_.toInt)
val (_, Some((p1, p2))) = Ps.zipWithIndex.foldLeft((Map[Int, Int](), None: Option[(Int, Int)])) {
case ((map, None), (p, i)) =>
if (map isDefinedAt C - p) map -> Some(map(C - p) -> (i + 1))
else (map updated (p, i + 1), None)
case (answer, _) => answer
}
println("Case #%d: %d %d" format (n, p1, p2))
}
}