How to keep duplicate items with set subtraction? - list

By groovy way, the code like:
def l1 = [] as List;
def l2 = [] as List;
for(int i = 0; i < 5; i++) {
l1 << i;
l2 << i;
l1 << i;
}
println(l1);
println(l2);
def l = l1-l2;
println(l);
The l is empty, but I want it be [0,1,2,3,4], just subtract the item once(if there is only on item in l2).

It works that way, because List.minus(Object el) searches for all elements matching el object and removes them from the input list. Alternatively you can make usage of List.removeElement(Object el) which searches for the first element and removes it from the list. This method can be combined with Groovy's inject method:
def l1 = [] as List
def l2 = [] as List
for(int i = 0; i < 5; i++) {
l1 << i
l2 << i
l1 << i
}
def l3 = l2.inject(l1) { List list, el ->
list.removeElement(el)
return list
}
println "l1 is ${l1}"
println "l2 is ${l2}"
println "l3 is ${l3}"
Output:
l1 is [0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
l2 is [0, 1, 2, 3, 4]
l3 is [0, 1, 2, 3, 4]
In this example we use l2 list to iterate over its elements and we pass l1 as our initial value to inject method. Then for each element from l2 list we remove the list we passed to the inject method and we return it so in the next iteration step this list is seen as list variable in the closure passed to inject. List.removeElement(Object el) is a safe method and there is no exception thrown if we try to remove an element that does not exist in the list.
However the code I have shown you has one significant drawback - it passes l1 to inject method and this list gets modified by it. That's why when you print l1 in the end you will see it is equal l3 we just created with inject method. The solution to this problem is fairly simple - instead of passing a refernce to l1 you can create a copy of this list, e.g. with new ArrayList<>(l1) and now l1 list does not gets updated by the inject method.
def l3 = l2.inject(new ArrayList<>(l1)) { List list, el ->
list.removeElement(el)
return list
}
Hope it helps.

The problem is that removal is done on the basis of element equality.
As an alternative, you can use indices to search the larger list, and build a diff list that includes all elements from l1 except the ones at first index of matches:
//find the first index of each l2 element in l1:
def match = l2.collect{l1.indexOf(it)}
//find indices of all elements that were not found in l1
def indices = (0..(-1+l1.size())).grep{!match.contains(it)}
//make a list of all elements that were not selected
//and that's basically the result of YOUR l1-l2
def diff = indices.collect{l1[it]}
println(diff)
That outputs:
[0, 1, 2, 3, 4]
Please note that this is not a generic method. It's completely based on your example above and assumes, for example, that l1 is a superset of l2, but it gives an idea.

Related

How would I get a list of pairs where every element from list1 is paired with some element from list2?

So I have this problem in my head that I'm trying to solve iteratively instead of recursively, but the solution seems to elude me despite it seemingly being so easy.
Let's say I have two lists
l1 = [a,b,c]
l2 = [1,2,3]
I want a list, where every element from l1 is paired with some element from l2. So it'll be like below:
[
[(a,1), (b,1), (c,1)],
[(a,1), (b,1), (c,2)],
[(a,1), (b,1), (c,3)],
[(a,1), (b,2), (c,1)],
[(a,1), (b,2), (c,2)],
[(a,1), (b,2), (c,3)],
[(a,1), (b,3), (c,1)],
[(a,1), (b,3), (c,2)],
[(a,1), (b,3), (c,3)],
...
]
Note that this is a bit different than simply getting a cross product (cartesian product).
Doing something like
for i in l1:
for j in l2:
...
doesn't quite work here because once you have the (a,1) pair for example, you have to jump to b instead of continuing to (a,2).
From the looks of it, it seems like it shouldn't be too difficult to formulate loops to make this result, but it's not coming to me immediately. I did make a recursive solution in python for your reference though.
l1 = ['a','b','c']
l2 = [1,2,3]
l3 = []
def makepair(res,cur,l1,l2):
if(l1==[]):
res.append(cur)
else:
for i in l2:
temp = cur[:]
temp.append((l1[0],i))
makepair(res,temp,l1[1:],l2)
makepair(l3,[],l1,l2)
for p in l3:
print(p)
The above code basically prints the example I explained. Can someone help me write this iteratively? I don't care about which language.
Note that this is a bit different than simply getting a cross product (cartesian product).
Actually, it is exactly a Cartesian product, of list2 with list2 with list2, using list1 as indices.
Note that cross product and Cartesian product are pretty unrelated. In python, you can get the Cartesian product with the standard library, using itertools.product. For the cross product, use the numpy library.
Using itertools.product
from itertools import product
list1 = ['a','b','c']
list2 = [1,2,3]
print( [list(zip(list1, p)) for p in product(list2, repeat=len(list1))] )
# [[('a', 1), ('b', 1), ('c', 1)],
# [('a', 1), ('b', 1), ('c', 2)],
# [('a', 1), ('b', 1), ('c', 3)],
# [('a', 1), ('b', 2), ('c', 1)],
# ...,
# [('a', 3), ('b', 3), ('c', 3)]]
Using for-loops
Of course, if the number of elements in list1 is small and constant, python's itertools.product is equivalent to nested simple loops:
def indexed_cartesian_product(l1, l2):
a, b, c = l1
for x in l2:
for y in l2:
for z in l2:
yield ((a, x), (b, y), (c, z))
print(list(indexed_cartesian_product('abc', [1,2,3])))
# [(('a', 1), ('b', 1), ('c', 1)),
# (('a', 1), ('b', 1), ('c', 2)),
# (('a', 1), ('b', 1), ('c', 3)),
# (('a', 1), ('b', 2), ('c', 1)),
# ...,
# (('a', 3), ('b', 3), ('c', 3))]
I wrote up a solution that basically translates the recursion into a stack. Afterall, all recursions run on a stack. (Link if you want to play with it yourself)
l1 = ['a','b','c']
l2 = [1,2,3]
l3 = []
stack = [[]]
while(len(stack)>0):
check = stack.pop()
if (len(check) == len(l1)):
l3.append(check)
else:
for e in l2:
stack.append(check+[(l1[len(check)],e)])
print(l3)
If we really wanted to save memory, I think this could be done without building the stack like this though. But considering the stack would be at most as big as the resulting list, therefore needing that much space anyway, I guess it's not a priority in my problem statement. But if we change up the problem a little bit and say we are checking if a "specific" combination exists, then the space can be wasteful. Afterall, building the entire combination will create a size of (len_l2)^(len_l1). Because this is exponential, it can get nasty really fast, so I think it's worth considering clever solutions that won't build the stack like this. (Note, the stack at each point should be smaller than (len_l2)^(len_l1), but I don't know how much smaller. Not sure how much smaller it would be on average, and also not sure how much smaller it is at its worst point. But I think it'll still be exponential)
An example scenario for finding a "specific" case might be if both l1 and l2 are made of numbers, and you are getting the sum of (each element in l1)*(some element in l2), and you must check whether there is some combination where the sum matches a specific number. In such a case, solutions using stuff like itertools.product start to become less useful because if you have to iterate through so much data, ideally you want to break the moment you find your specific case instead of building all possible options first and then iterating through them to see if the case exists.
I also made a pretty messy solution that doesn't build a stack. I did this in C++ instead of python because my original goal was to do this idea in C++ anyways. (Just initially used python for better readability)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//cur will be in the form of [0,1,2], and would need to be transformed to [(a,1),(b,2),(c,3)]
void add_to_l3(vector<vector<pair<char,int>>> &l3, vector<char> &l1, vector<int> &l2, vector<int> &cur) {
vector<pair<char,int>> paired_cur(l1.size());
for(int x=0; x<l1.size(); x++){
paired_cur[x] = {l1[x], l2[cur[x]]};
}
l3.push_back(paired_cur);
}
int main()
{
vector<char> l1 = {'a','b','c'};
vector<int> l2 = {1, 2, 3};
vector<vector<pair<char,int>>> l3;
vector<int> cur(l1.size(), 0);
//cur[i] stores the index of the number at l2 that would be paired with l1[i]
int i = l1.size()-1;
//Start with the base case of [(a,1),(b,1),(c,1)] and keep the pointer at the back of the array pointing at (c,1)
//We iterate through l2's spot at the pointer such as [(a,1),(b,1),(c,2)] until we can't any more (which is at [(a,1),(b,1),(c,3)])
//Afterwards, we decrement the pointer and notify that we decremented the pointer. We would now be pointing at (b,1)
//If we can increment the l2's spot there, increment it, and then reset all the l2's spot for every element in the right of that to the base case. Start the pointer at the back of the array again.
//If we couldn't increment the L2's spot, keep decrementing the pointer until we find the location that could increment l2's spot, and then reset all l2's spot for elements to the right of it.
//Do this until we run out of spaces to decrement the pointer.
add_to_l3(l3,l1,l2,cur);
bool back=false;
//This boolean checks if we decremented the pointer
while(i>=0) {
if(cur[i] < l2.size()-1) {
cur[i]++;
if(back==true) {
for(i=i+1; i<l1.size(); i++) {
cur[i]=0;
}
back=false;
i=l1.size()-1;
}
//cout << i << endl;
add_to_l3(l3,l1,l2,cur);
}
else {
i--;
back=true;
}
}
for (auto &e : l3) {
for (auto &p : e) {
cout << '(' << p.first << ',' << p.second << ')';
}
cout << endl;
}
return 0;
}
The idea behind this is that we start with
[(a,1),(b,1),(c,1)]
and start by pointing at (c,1).
Increment the l2 part of the pair until we can't like so:
[(a,1),(b,1),(c,2)] and [(a,1),(b,1),(c,3)]
Then we backtrack the pointer to point at (b,1) and increment the l2 part, or if that is also maxed out (because it is (b,3)), we keep backtracking until we reach a location where we can increment the l2 part. Once we increment the l2 part, we reset all the l2 part to the right of it to the base case.
So when we are pointing at (b,1), that gets changed to (b,2). And then (c,3) gets reset to (c,1). Therefore, we have [(a,1),(b,2),(c,1)]
It's messy but this allows us to be holding onto just one set of combination at a time, while also having full control of observing each combination at the moment we reach it.
Please let me know if you have any feedback of making this simpler
Starting with just an empty row, then building up from that one column at a time (Python implementation):
l1 = ['a','b','c']
l2 = [1,2,3]
l3 = [[]]
for column in l1:
l3 = [
row + [(column, value)]
for row in l3
for value in l2
]
for p in l3:
print(p)
Same but written more in the style of other languages:
l3 = [[]]
for column in l1:
new_l3 = []
for row in l3:
for value in l2:
new_row = row + [(column, value)]
new_l3.append(new_row)
l3 = new_l3
Bonus solution using itertools (producing an iterator of tuples of pairs instead of a list of list of pairs, but that's easy to adjust if really necessary.
from itertools import repeat, product
l1 = ['a','b','c']
l2 = [1,2,3]
result = product(*map(zip, map(repeat, l1), repeat(l2)))
for p in result:
print(p)

Pattern match against List 'init' and 'last' instead of 'head' and 'tail'

I know that it's possible to easily pattern match against the head (or an arbitrary number of initial elements) and tail of a List:
val items = List(1, 2, 3, 4)
val first :: rest = items
println(first, rest) // 1, List(2, 3, 4)
However, I would like to do it the other way - can you use a pattern to get the init and last of the list?
val items = List(1, 2, 3, 4)
val rest ??? last = items
println(rest, last) // List(1, 2, 3), 4
In JavaScript this would look like:
const [...init, last] = items
You can use the :+ custom extractor object.
So the code would look like this:
val rest :+ last = items
However, note that this is equally inefficient than doing:
val last :: rest = items.reverse
But, if you then need to decompose rest again, then reversing it first will be more efficient.
Finally, remember both are unsafe since they will throw in case the List is empty.
This should work:
val xs :+ x = items
Check out: https://www.scala-lang.org/files/archive/api/2.12.0/scala/collection/Seq.html#:+(elem:A):Seq[A]

Finding index of row from a list

I am trying to get the index of a row using Scala from a list consisting of lists of integers List[List[Int]]. I already have two functions that given the row index/column index and the grid as parameters, it outputs all the elements in that row. What I need is a function that given a particular element (eg: 0), it finds its row index and column index and puts them in a list: List[(Int, Int)]. I tried to code a function that gives back an index when encountering 0 and then I passed the function to the whole grid. I don't know if I'm doing it the right way. Also, I couldn't figure out how to return the list.
Also, I cannot use any loops.
Thanks in advance.
def Possibilities(): List[Int] = {
def getRowIndex(elem: Int): Int = elem match
{
case 0 => sudoku.grid.indexOf(sudoku.row(elem))
case x => x
}
val result1 = sudoku.grid map {row => row map getRowIndex}
}
I think with two dimensions it is much easier to write such a method with for comprehensions.
Given a List[List[Int]] like this:
val grid = List(
List(1, 2, 3),
List(4, 5, 6),
List(3, 2, 1))
we can simply walk through all the rows and columns, and check whether each element is the one we are looking for:
def possibilities(findElem: Int): List[(Int, Int)] = {
for (
(row, rowIndex) <- grid.zipWithIndex;
(elem, colIndex) <- row.zipWithIndex
if elem == findElem
) yield (rowIndex, colIndex)
}
The yield keyword creates a collection of the results of the for loop. You can find more details on Scala's forloop syntax here (and a more thorough discussion on how this relates to map, flatMap, etc. here).
So, if you don't want to use a for loop, simply 'translate' it into an equivalent expression using map. flatMap, and withFilter:
def possibilities(findElem: Int): List[(Int, Int)] = {
grid.zipWithIndex flatMap { rowAndIndex =>
rowAndIndex._1.zipWithIndex.withFilter(_._1 == findElem) map { colAndIndex =>
(rowAndIndex._2, colAndIndex._2)
}
}
}
Step 1, create a collection of all possible tuples of indices, with a for comprehension (for looks like a loop but it is not)
val tuples = for (i <- grid.indices; j <- grid.head.indices) yield (i, j)
Step 2, filter this collection
tuples.filter { case (i, j) => grid(i)(j) == valueToFind }

Scala insert into list at specific locations

This is the problem that I did solve, however being a total imperative Scala noob, I feel I found something totally not elegant. Any ideas of improvement appreciated.
val l1 = 4 :: 1 :: 2 :: 3 :: 4 :: Nil // original list
val insert = List(88,99) // list I want to insert on certain places
// method that finds all indexes of a particular element in a particular list
def indexesOf(element:Any, inList:List[Any]) = {
var indexes = List[Int]()
for(i <- 0 until inList.length) {
if(inList(i) == element) indexes = indexes :+ i
}
indexes
}
var indexes = indexesOf(4, l1) // get indexes where 4 appears in the original list
println(indexes)
var result = List[Any]()
// iterate through indexes and insert in front
for(i <- 0 until indexes.length) {
var prev = if(i == 0) 0 else indexes(i-1)
result = result ::: l1.slice(prev, indexes(i)) ::: insert
}
result = result ::: l1.drop(indexes.last) // append the last bit from original list
println(result)
I was thinking more elegant solution would be achievable with something like this, but that's just pure speculation.
var final:List[Any] = (0 /: indexes) {(final, i) => final ::: ins ::: l1.slice(i, indexes(i))
def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) = {
xs.map(x => if (p(x)) extra ::: List(x) else List(x)).flatten
}
scala> insert(List(4,1,2,3,4),List(88,99)){_ == 4}
res3: List[Int] = List(88, 99, 4, 1, 2, 3, 88, 99, 4)
Edit: explanation added.
Our goal here is to insert a list (called extra) in front of selected elements in another list (here called xs--commonly used for lists, as if one thing is x then lots of them must be the plural xs). We want this to work on any type of list we might have, so we annotate it with the generic type [A].
Which elements are candidates for insertion? When writing the function, we don't know, so we provide a function that says true or false for each element (p: A => Boolean).
Now, for each element in the list x, we check--should we make the insertion (i.e. is p(x) true)? If yes, we just build it: extra ::: List(x) is just the elements of extra followed by the single item x. (It might be better to write this as extra :+ x--add the single item at the end.) If no, we have only the single item, but we make it List(x) instead of just x because we want everything to have the same type. So now, if we have something like
4 1 2 3 4
and our condition is that we insert 5 6 before 4, we generate
List(5 6 4) List(1) List(2) List(3) List(5 6 4)
This is exactly what we want, except we have a list of lists. To get rid of the inner lists and flatten everything into a single list, we just call flatten.
The flatten trick is cute, I wouldn't have thought of using map here myself. From my perspective this problem is a typical application for a fold, as you want go through the list and "collect" something (the result list). As we don't want our result list backwards, foldRight (a.k.a. :\) is here the right version:
def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) =
xs.foldRight(List[A]())((x,xs) => if (p(x)) extra ::: (x :: xs) else x :: xs)
Here's another possibility, using Seq#patch to handle the actual inserts. You need to foldRight so that later indices are handled first (inserts modify the indices of all elements after the insert, so it would be tricky otherwise).
def insert[A](xs: Seq[A], ys: Seq[A])(pred: A => Boolean) = {
val positions = xs.zipWithIndex filter(x => pred(x._1)) map(_._2)
positions.foldRight(xs) { (pos, xs) => xs patch (pos, ys, 0) }
}

Right way to swap x elements in List

I started to learn Scala language and I have a question. How do you think, is it a right way to swap first and last x elements in List in a functional style?
def swap(l: List[Any], x: Int) = {
val l1 = l.take(x)
val l2 = l.slice(x, l.length - x)
val l3 = l.takeRight(x)
l3 ::: l2 ::: l1
}
It doesn't matter what happened if x would be more than half list length. I'm interested to find out algorithm.
This code is correct and is in a reasonable functional style. It's not the most efficient since it has to traverse the list four times to create the pieces l1 through l3. Also, you probably want to preserve the type that the list contains, so a slight improvement is:
def swap[A](l: List[A], x: Int) = {
val (l1,rest) = l.splitAt(x)
val (l2,l3) = rest.splitAt(rest.length-x)
l3 ::: l2 ::: l1
}
I tried it and it worked fine:
scala> swap(List(1, 2, 3, 4, 5),2)
res0: List[Any] = List(4, 5, 3, 1, 2)
Is there anything wrong with the code you provided yourself?