I was unable to solve this question. Looking for the help of algo expert.
It will be great if the solution is provided in javascript, but it does not matter.
Given input:
[
[1,2,3]
[4,5,6]
[7,8]
...
]
Expected output:
[
[1,4,7]
[1,4,8]
[1,5,7]
[1,5,8]
[1,6,7]
[1,6,8]
[2,4,7]
[2,4,8]
[2,5,7]
[2,5,8]
[2,6,7]
[2,6,8]
[3,4,7]
[3,4,8]
[3,5,7]
[3,5,8]
[3,6,7]
[3,6,8]
]
You can use a recursive function. Here I have chosen to implement it as a generator, using * and yield. The caller can either iterate the function's result directly with a for loop, or turn it into an array:
function * generateCombis(data) {
if (data.length === 0) return yield [];
let [arr, ...rest] = data;
for (let val of arr) {
for (let combi of generateCombis(rest)) {
yield [val, ...combi];
}
}
}
let data = [
[1,2,3],
[4,5,6],
[7,8]
];
let result = Array.from(generateCombis(data));
console.log(result);
Related
I'm really interested in how this algorithm can be implemented. If possible, it would be great to see an implementation with and without recursion. I am new to the language so I would be very grateful for help. All I could come up with was this code and it goes no further:
print(counterOccur("aabcdddeabb"))
def counterOccur(string: String) =
string.toCharArray.toList.map(char => {
if (!char.charValue().equals(char.charValue() + 1)) (char, counter)
else (char, counter + 1)
})
I realize that it's not even close to the truth, I just don't even have a clue what else could be used.
First solution with using recursion. I take Char by Char from string and check if last element in the Vector is the same as current. If elements the same I update last element by increasing count(It is first case). If last element does not the same I just add new element to the Vector(second case). When I took all Chars from the string I just return result.
def counterOccur(string: String): Vector[(Char, Int)] = {
#tailrec
def loop(str: List[Char], result: Vector[(Char, Int)]): Vector[(Char, Int)] = {
str match {
case x :: xs if result.lastOption.exists(_._1.equals(x)) =>
val count = result(result.size - 1)._2
loop(xs, result.updated(result.size - 1, (x, count + 1)))
case x :: xs =>
loop(xs, result :+ (x, 1))
case Nil => result
}
}
loop(string.toList, Vector.empty[(Char, Int)])
}
println(counterOccur("aabcdddeabb"))
Second solution that does not use recursion. It works the same, but instead of the recursion it is using foldLeft.
def counterOccur2(string: String): Vector[(Char, Int)] = {
string.foldLeft(Vector.empty[(Char, Int)])((r, v) => {
val lastElementIndex = r.size - 1
if (r.lastOption.exists(lv => lv._1.equals(v))) {
r.updated(lastElementIndex, (v, r(lastElementIndex)._2 + 1))
} else {
r :+ (v, 1)
}
})
}
println(counterOccur2("aabcdddeabb"))
You can use a very simple foldLeft to accumulate. You also don't need toCharArray and toList because strings are implicitly convertible to Seq[Char]:
"aabcdddeabb".foldLeft(collection.mutable.ListBuffer[(Char,Int)]()){ (acc, elm) =>
acc.lastOption match {
case Some((c, i)) if c == elm =>
acc.dropRightInPlace(1).addOne((elm, i+1))
case _ =>
acc.addOne((elm, 1))
}
}
Here is a solution using foldLeft and a custom State case class:
def countConsecutives[A](data: List[A]): List[(A, Int)] = {
final case class State(currentElem: A, currentCount: Int, acc: List[(A, Int)]) {
def result: List[(A, Int)] =
((currentElem -> currentCount) :: acc).reverse
def nextState(newElem: A): State =
if (newElem == currentElem)
this.copy(currentCount = this.currentCount + 1)
else
State(
currentElem = newElem,
currentCount = 1,
acc = (this.currentElem -> this.currentCount) :: this.acc
)
}
object State {
def initial(a: A): State =
State(
currentElem = a,
currentCount = 1,
acc = List.empty
)
}
data match {
case a :: tail =>
tail.foldLeft(State.initial(a)) {
case (state, newElem) =>
state.nextState(newElem)
}.result
case Nil =>
List.empty
}
}
You can see the code running here.
One possibility is to use the unfold method. This method is defined for several collection types, here I'm using it to produce an Iterator (documented here for version 2.13.8):
def spans[A](as: Seq[A]): Iterator[Seq[A]] =
Iterator.unfold(as) {
case head +: tail =>
val (span, rest) = tail.span(_ == head)
Some((head +: span, rest))
case _ =>
None
}
unfold starts from a state and applies a function that returns, either:
None if we want to signal that the collection ended
Some of a pair that contains the next item of the collection we want to produce and the "remaining" state that will be fed to the next iteration.
In this example in particular, we start from a sequence of A called as (which can be a sequence of characters) and at each iteration:
if there's at least one item
we split head and tail
we further split the tail into the longest prefix that contains items equal to the head and the rest
we return the head and the prefix we got above as the next item
we return the rest of the collection as the state for the following iteration
otherwise, we return None as there's nothing more to be done
The result is a fairly flexible function that can be used to group together spans of equal items. You can then define the function you wanted initially in terms of this:
def spanLengths[A](as: Seq[A]): Iterator[(A, Int)] =
spans(as).map(a => a.head -> a.length)
This can be probably made more generic and its performance improved, but I hope this can be an helpful example about another possible approach. While folding a collection is a recursive approach, unfolding is referred to as a corecursive one (Wikipedia article).
You can play around with this code here on Scastie.
For
str = "aabcdddeabb"
you could extract matches of the regular expression
rgx = /(.)\1*/
to obtain the array
["aa", "b", "c", "ddd", "e", "a", "bb"]
and then map each element of the array to the desired string.1
def counterOccur(str: String): List[(Char, Int)] = {
"""(.)\1*""".r
.findAllIn(str)
.map(m => (m.charAt(0), m.length)).toList
}
counterOccur("aabcdddeabb")
#=> res0: List[(Char, Int)] = List((a,2), (b,1), (c,1), (d,3), (e,1), (a,1), (b,2))
The regular expression reads, "match any character and save it to capture group 1 ((.)), then match the content of capture group 1 zero or more times (\1*).
1. Scala code kindly provided by #Thefourthbird.
I want to transform a Seq of keys/values to a Map. The first element of the sequence is reserved, so the list of pairs starts in the position 1.
The question is: Is possible to implement this function using a more functional way?
def list2Map(plainMap:Seq[String]) = {
var map = Map[String, String]()
var idx = 1;
while(plainMap.size > idx) {
val key = plainMap(idx)
idx += 1
val value = plainMap(idx)
idx += 1
map = map + (key -> value)
}
map
}
assert( list2Map( Seq("reserved slot","key0","value0","key1","value1","key2","value2") ) == Map( ("key0"->"value0"),("key1"->"value1"),("key2"->"value2") ) )
I am new in Scala, and I know that there are a lot of different ways to iterate over a collection, but I don't found a forEach way to read two elements per iteration, starting in the element 1.
PS: Thanks folks. I am learning a lot with everyone response!!
list.drop(1).grouped(2).map { x => x.head -> x.last }.toMap
You mean something like this?:
val list = List("reserved slot", "key0", "value0", "key1", "value1", "key2", "value2")
val list4Map = list.tail.grouped(2).map { listBy2 => (listBy2(0), listBy2(1)) }.toList
val map = Map(list4Map: _*)
Maybe you would like some recursive one:
def seq2Map[T](seq: Seq[T]) = {
def rec(seq: Seq[T], map: Map[T,T] = Map.empty[T,T]): Map[T,T] = seq match {
case h :: t :: e => rec(e, map + (h -> t))
case _ => map
}
rec(seq.tail)
}
(for { Seq(k, v) <- list.tail.grouped(2) } yield k -> v).toMap
covers trailing key too
This question already has an answer here:
Index of element in sorted()
(1 answer)
Closed 7 years ago.
I'm trying to return the indices of an array which correspond to the sorted values. For example,
let arr = [7, 10, -3]
let idxs = argsort(arr) // [2, 0, 1]
My attempt works but is not pretty, and only functions for CGFloat. I'm looking for some ways in which I can improve the function, make it generic and easier to read. The code just looks ugly,
func argsortCGFloat( a : [CGFloat] ) -> [Int] {
/* 1. Values are wrapped in (index, values) tuples */
let wrapped_array = Array(Zip2(indices(a),a))
/* 2. A comparator compares the numerical value from
two tuples and the array is sorted */
func comparator(a: (index : Int, value : CGFloat), b: (index : Int, value : CGFloat)) -> Bool {
return a.value < b.value
}
var values = sorted(wrapped_array, comparator)
/* 3. The sorted indexes are extracted from the sorted
array of tuples */
var sorted_indexes: [Int] = []
for pair in values {
sorted_indexes.append(pair.0)
}
return sorted_indexes
}
You can do it by creating an array of indexes, and sorting them using the array from the outer context, like this:
func argsort<T:Comparable>( a : [T] ) -> [Int] {
var r = Array(indices(a))
r.sort({ a[$0] > a[$1] })
return r
}
let arr = [7, 10, -3]
let idxs = argsort(arr)
println (idxs)
The key-sorting according to values of a dictionary with simple Doubles or Ints works perfectly fine according to the example provided here....
But what about more complex dictionary-structures ?
I have a dictionary with dictionary-values that each consist of an array of Double-Tuples. (pretty complex, I know....).
And I would like to sort the dictionary-values according to the sum of the Second-Tuple-Array. (i.e. all second-tuple elements form an array and this array is summed-up; then sort the array-sums according to the smallest value). But all that still without loosing information on the dictionary-key. The result of the asked method shall return an array of keys according to the sorted result of "second-tuple-summed-up-array-results).
Here my "poor" trial for this problem :
I tried to sort the keys according to the values of the first-Tuple of the array-of-Tuples with the following Playground example (see below). But it does not perform yet....
This works for basic types:
extension Dictionary {
func keysSortedByValue(isOrderedBefore:(Value, Value) -> Bool) -> [Key] {
return sorted(self) {
let (lk, lv) = $0
let (rk, rv) = $1
return isOrderedBefore(lv, rv)
}.map { (k,v) in k }
}
}
let dict = ["a":2, "c":1, "b":3]
dict.keysSortedByValue(<) // result array of keys: ["c", "a", "b"]
dict.keysSortedByValue(>) // result array of keys: ["b", "a", "c"]
But in my more complex case, it doesn't work:
var criteria_array1 = [(Double, Double)]()
var criteria_array2 = [Double]()
var criteria_dict1 = [String:[(Double, Double)]]()
var criteria_dict2 = [String:[Double]]()
// Random creation of two dictionaries with a complex value-structure...
// Dictionary1: keys = Strings, values = array of Double-Tuples
// Dictionary2: keys = Strings, values = array of Doubles
for n in 1...5 {
let currentTopoString: String = "topo_\(n)"
for t in 0...14 {
let a: Double = Double(arc4random_uniform(1000))
let b: Double = Double(Double(arc4random_uniform(1000))/1000)
criteria_array1 += [(a, b)]
criteria_array2 += [b]
}
criteria_dict1[currentTopoString] = criteria_array1
criteria_dict2[currentTopoString] = criteria_array2
criteria_array1.removeAll()
criteria_array2.removeAll()
}
// the two following instruction generate compiler errors....
// why ???????????
// How could a complex dictionary-value-structure be applied to a sortingMethod ??
criteria_dict1.keysSortedByFirstTupleValue(>)
criteria_dict2.keysSortedByFirstTupleValue(>)
This is a question of implementing the isOrderedBefore function appropriately. Just passing in > is not going to cut it (even assuming there was an implementation of > for arrays of tuples, it almost certainly wouldn't do the comparison-of-summation you are looking for).
If I understand your goal correctly, you want to sort the keys based on the value of the sum of one of the tuple entries in an array of tuples?
So something like this:
criteria_dict1.keysSortedByValue { lhs, rhs in
// if you actually want to sort by sum of first element in tuple,
// change next.1 to next.0
let left_sum = reduce(lhs, 0) { total, next in total + next.1 }
let right_sum = reduce(rhs, 0) { total, next in total + next.1 }
return left_sum > right_sum
}
This is quite inefficient, since you're summing the array for every comparison – in practice you may want to memoize it, or maybe rethink the problem in terms of a different data structure if you do this a lot.
object BubbleSort {
def main(args : Array[String]) : Unit = {
bubbleSort(Array(50,33,62,21,100)) foreach println
}
def bubbleSort(a:Array[Int]):Array[Int]={
for(i<- 1 to a.length-1){
for(j <- (i-1) to 0 by -1){
if(a(j)>a(j+1)){
val temp=a(j+1)
a(j+1)=a(j)
a(j)=temp
}
}
}
a
}
}
I have the above code supposedly implementing bubble sort in Scala. It is sorting the given numbers in the main but is it a well implemented Bubble Sorting algorithm?
Also what does this line of code mean in pseudocode: for(j <- (i-1) to 0 by -1){
I can't understand it.
Thanks for your help
The best way to figure out what a bit of Scala code does is to run it in the REPL:
scala> 5 to 0 by -1
res0: scala.collection.immutable.Range = Range(5, 4, 3, 2, 1, 0)
So that code counts from (i-1) to 0, backwards.
More generally, x to y creates a Range from integer x to integer y. The by portion modifies this counting. For example, 0 to 6 by 2 means "count from 0 to 6 by 2", or Range(0, 2, 4, 6). In our case, by -1 indicates that we should count backwards by 1.
As for understanding how bubble sort works, you should read the Wikipedia article and use that to help you understand what the code is doing.
This can be the shortest functional implementation of Bubble sort
/**
* Functional implementation of bubble sort
* sort function swaps each element in the given list and create new list and iterate the same operation for length of the list times.
* sort function takes three parameters
* a) iteration list -> this is used to track the iteration. after each iteration element is dropped so that sort function exists the iteration list is empty
* b) source list -> this is source list taken for element wise sorting
* c) result -> stores the element as it get sorted and at end of each iteration, it will be the source for next sort iteration
*/
object Test extends App {
def bubblesort(source: List[Int]) : List[Int] = {
#tailrec
def sort(iteration: List[Int], source: List[Int] , result: List[Int]) : List[Int]= source match {
case h1 :: h2 :: rest => if(h1 > h2) sort(iteration, h1 :: rest, result :+ h2) else sort(iteration, h2 :: rest, result :+ h1)
case l:: Nil => sort(iteration, Nil, result :+ l)
case Nil => if(iteration.isEmpty) return result else sort(iteration.dropRight(1), result, Nil )
}
sort(source,source,Nil)
}
println(bubblesort(List(4,3,2,224,15,17,9,4,225,1,7)))
//List(1, 2, 3, 4, 4, 7, 9, 15, 17, 224, 225)
}
The example you have posted is basically a imperative or Java way of doing bubble sort in Scala which is not bad but defies the purpose of Functional Programming in Scala.. the same code can we written sorter like below (basically combining both the for loops in one line and doing a range on the source length)
def imperativeBubbleSort[T <% Ordered[T]](source: Array[T]): Array[T] = {
for (i <- 0 until source.length - 1; j <- 0 until source.length - 1 - i) {
if (source(j) > source(j + 1)) {
val temp = source(j)
source(j) = source(j + 1)
source(j + 1) = temp
}
}
source
}
Scala Flavor of bubble sort can be different and simple example is below
(basically usage of Pattern matching..)
def bubbleSort[T <% Ordered[T]](inputList: List[T]): List[T] = {
def sort(source: List[T], result: List[T]) = {
if (source.isEmpty) result
else bubble(source, Nil, result)
}
def bubble(source: List[T], tempList: List[T], result: List[T]): List[T] = source match {
case h1 :: h2 :: t =>
if (h1 > h2) bubble(h1 :: t, h2 :: tempList, result)
else bubble(h2 :: t, h1 :: tempList, result)
case h1 :: t => sort(tempList, h1 :: result)
}
sort(inputList, Nil)
}
#tailrec
def bubbleSort(payload: List[Int], newPayload: List[Int], result: List[Int]): List[Int] = {
payload match {
case Nil => result
case s::Nil => bubbleSort(newPayload, List.empty, s::result)
case x::xs => x.compareTo(xs.head) match {
case 0 => bubbleSort(xs, x::newPayload, result)
case 1 => bubbleSort(x::xs.tail, xs.head::newPayload, result)
case -1 => bubbleSort(xs, x::newPayload, result)
}
}
}
val payload = List(7, 2, 5, 10, 4, 9, 12)
bubbleSort(payload, List.empty, List.empty)