I'd like to take an input array and a set of possible sizes and partition the array into sub arrays that each have a count of the biggest possible bucket size that is smaller than the remaining number of items.
So given the input array...
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
And the sizes...
[10, 5, 3, 2, 1]
It would return an array like...
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13], [14]]
First partitioning 10 and then 3 and then 1.
I can do this in a very clunky way using while loops and so on but I wondered if this sort of algorithm had a name of some sorts that I could research some more elegant ways of doing it.
Thanks to #AnandUndavia, I solved this not as an array partitioning exercise but as a Coin Change problem.
I was able to solve this using this function... (In Swift)
func separate(numberOfItems n: Int, bucketSizes sizes: [Int]) -> [Int] {
var output = [Int]()
var remaining = n
for size in sizes {
while remaining >= size {
output.append(size)
remaining -= size
}
}
return output
}
Now with my array of sizes I can easily solve the rest of the problem that I was working on :D
You can achieve this in single loop also. Something like this is JS:
var inputArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
var sizeArray = [10, 3, 5, 2, 1];
var outputArray = [];
sizeArray.sort(function(a, b) { return b-a}); // Sort array in decreasing order
while(sizeArray.length > 0 && inputArray.length > 0){
var m = sizeArray[0];
sizeArray = sizeArray.slice(1); // Pop the first element from Size Array
if(m <= inputArray.length){
outputArray.push(inputArray.slice(0, m)); // Extract first m elements from inputArray if its size is greater than m
inputArray = inputArray.slice(m);
}
}
console.log(outputArray);
Problem:
I have two arrays A and B:
A = [0, 1, 2, 3]; %A will always be from 0 to N where N in this case is 3.
B = [0, 1, 3, 1, 9, 4, 6, 2, 5, 9, 10, 11, 3, 8, 1, 5, 9, 10];
weights_B = [3, 4, 5, 6];
I want to compare the first element of A to the first 3 elements of B and the second element of A to the next 4 elements of B. If the elements of A are equal I remove it from B. So in example:
if (A(1) == B(1:3))
remove A(1) from B
Similarly,
I want to compare A(2) to the next 4 elements of B i.e. to B(4:7):
if (A(2) == B(4:7))
remove A(2) from B
I want to compare A(3) to the next 5 elements of B i.e. to B(8:12)
if (A(3) == B(8:12))
remove A(3) from B
I want to compare A(4) to the next 6 elements of B i.e. to B(13:18)
if (A(4) == B(13:18))
remove A(4) from B
Note: The array weights_B determines the number of elements in B that should be respectively compared to A(1), A(2), .. , A(4)
So in the end B should have the following elements:
B = [1, 3, 9, 4, 6, 5, 9, 10, 11, 8, 1, 5, 9, 10];
Needed Solution:
Is there any way I can do this without having to hard-code the indices?
Here's a way without hard-coding:
Bw = mat2cell(B, 1, weights_B); % split into chunks
result = cell(size(Bw)); % initiallize result
for k = 1: numel(A)
result{k} = Bw{k}(Bw{k}~=A(k)); % fill each chunk of the result
end
result = [result{:}]; % concatenate into a row vector
For the sake of diversity, here's a way to do this using splitapply:
function out = q50982235
A = 0:3;
B = [0, 1, 3, 1, 9, 4, 6, 2, 5, 9, 10, 11, 3, 8, 1, 5, 9, 10];
weights_B = [3, 4, 5, 6];
a_ind = 0; % acts as a "global" variable for the inner function
G = repelem( 1:numel(weights_B), weights_B ); % this creates a vector of groups
out = cell2mat( splitapply(#movdif, B, G) );
function out = movdif(B)
a_ind = a_ind + 1;
out = {B(B ~= A(a_ind))};
end
end
The above works because the order of processed groups is predictable.
This solution requires R2015b.
Try this
A = [0, 1, 2, 3];
B = [0, 1, 3, 1, 9, 4, 6, 2, 5, 9, 10, 11, 3, 8, 1, 5, 9, 10];
weights_B = A + A(end);
border_0 = zeros(size(A));
border_1 = zeros(size(A));
border_0(1) = 1;
border_1(end) = length(B);
for i= 2:length(A)
border_0(i) = border_0(i-1) + weights_B(i-1);
border_1(i-1) = border_0(i)-1;
end
C = [];
for i= 1:length(border_0)
shift = 0;
if (i > 1)
shift = border_1(i-1);
end
C = [C B( find(B(border_0(i):border_1(i))~=A(i)) + shift )]
end
A = [0, 1];
B = [0, 1, 3, 1, 4, 5, 6];
% Split B into cells
C{1} = B(1:3) ; % this can be coded if more splits are required
C{2} = B(4:end) ;
% removing the lements
for i = 1:2
C{i}(C{i}==A(i))=[] ; % remove the elements in C{i} present in A(i)
end
cell2mat(C)
Since you want to compare the elements of A with first 3 and then 4 elements of B respectively, you would need to involve indexes.
You could simply use loop for it.
for(int i=0;i<B.length;i++){
if((A[0]==B[i])&&i<3){
B[i]=B[i+1];
}
else if((A[0]==B[i])&&i>3){}
B[i]=B[i+1];
}
Then adjust the updated size of array B.
Let’s say I have an array like the following:
1 2 3 4 5 6 7 8 9 1 2 3 4 5 1 2 3 4
I want many sub-arrays of contiguous numbers whose sum of every contiguous pair is less than 10
1 2 3 4 5, 6, 7, 8, 9, 1 2 3 4 5 1 2 3 4
How do I code it in scala in a functional idiomatic way?
// example no. 1
>Array(1, 2, 3, 4, 5, 6)...???
res0: List(Array(1, 2, 3, 4, 5), Array(6))
// example no. 2
>Array(3, 8, 1, 9, 1, 3)...???
res1: List(Array(3), Array(8, 1), Array(9), Array(1, 3))
Doing a foldRight makes it easier to use head and tail to build the resulting List.
val grouped = Array(3,8,1,9,1,3).foldRight(List.empty[Array[Int]]){case (n,acc) =>
if (acc.isEmpty) List(Array(n))
else if (acc.head.head + n < 10) n +: acc.head :: acc.tail
else Array(n) :: acc
} // List(Array(3), Array(8, 1), Array(9), Array(1, 3))
This should work (although it's a very inefficient way):
def group(threshold: Int)(seq: Seq[Int]): Seq[Seq[Int]] =
seq.reverse.tails.find(_.sum < threshold) match {
case None => Nil
case Some(Nil) => Nil
case Some(subSeq) =>
subSeq.reverse +: group(threshold)(seq.drop(subSeq.size))
}
group(10)(Array(3, 8, 1, 9, 1, 3))
List(Array(3), Array(8, 1), Array(9), Array(1, 3))
I have to implement a kind of an array or sequence or list, which supports the cheapest way of circulated forwarding and back winding of elements. See this example:
Original sequence: 1 2 3 4 5
Forwarded once: 5 1 2 3 4
Forwarded twice: 4 5 1 2 3
Same but opposite is for the back winding. What would be the cheapest and most Scala-style way of implementing this? In Java I could use LinkedList and it would do great... However, I could not find any definite answer for Scala.
Also, it also has to be easy to replace any given element by index, as in LinkedList.
UPDATE:
For the fastest, but not-so-idiomatic variant of algorithm (you know when you need it), refer to the answer of Petr Pudlák!!!
Immutable implementation
A ring buffer is a pair of an IndexedSeq and an Int pointer into this sequence. I provide code for a immutable version. Note that not all methods that might be useful are implemented; like the mutators that change the content of the IndexedSeq.
With this implementation, shifting is just creating one new object. So it's pretty efficient.
Example code
class RingBuffer[A](val index: Int, val data: IndexedSeq[A]) extends IndexedSeq[A] {
def shiftLeft = new RingBuffer((index + 1) % data.size, data)
def shiftRight = new RingBuffer((index + data.size - 1) % data.size, data)
def length = data.length
def apply(i: Int) = data((index + i) % data.size)
}
val rb = new RingBuffer(0, IndexedSeq(2,3,5,7,11))
println("plain: " + rb)
println("sl: " + rb.shiftLeft)
println("sr: " + rb.shiftRight)
Output
plain: Main(2, 3, 5, 7, 11)
sl: Main(3, 5, 7, 11, 2)
sr: Main(11, 2, 3, 5, 7)
Performance comparison to mutable implementations
The OP mentions that you should look at the mutable implementations (e.g. this answer), if you need performance. This is not true in general. As always: It depends.
Immutable
update: O(log n), which is basically the update complexity of the underlying IndexedSeq;
shifting: O(1), also involves creating a new object which may cost some cycles
Mutable
update: O(1), array update, as fast as it gets
shifting: O(n), you have to touch every element once; fast implementations on primitive arrays might still win against the immutable version for small arrays, because of constant factor
scala> val l = List(1,2,3,4,5)
l: List[Int] = List(1, 2, 3, 4, 5)
scala> val reorderings = Stream.continually(l.reverse).flatten.sliding(l.size).map(_.reverse)
reorderings: Iterator[scala.collection.immutable.Stream[Int]] = non-empty iterator
scala> reorderings.take(5).foreach(x => println(x.toList))
List(1, 2, 3, 4, 5)
List(5, 1, 2, 3, 4)
List(4, 5, 1, 2, 3)
List(3, 4, 5, 1, 2)
List(2, 3, 4, 5, 1)
I needed such an operation myself, here it is. Method rotate rotates the given indexed sequence (array) to the right (negative values shift to the left). The process is in-place, so no additional memory is required and the original array is modified.
It's not Scala-specific or functional at all, it's meant to be very fast.
import annotation.tailrec;
import scala.collection.mutable.IndexedSeq
// ...
#tailrec
def gcd(a: Int, b: Int): Int =
if (b == 0) a
else gcd(b, a % b);
#inline
def swap[A](a: IndexedSeq[A], idx: Int, value: A): A = {
val x = a(idx);
a(idx) = value;
return x;
}
/**
* Time complexity: O(a.size).
* Memory complexity: O(1).
*/
def rotate[A](a: IndexedSeq[A], shift: Int): Unit =
rotate(a, 0, a.size, shift);
def rotate[A](a: IndexedSeq[A], start: Int, end: Int, shift: Int): Unit = {
val len = end - start;
if (len == 0)
return;
var s = shift % len;
if (shift == 0)
return;
if (s < 0)
s = len + s;
val c = gcd(len, s);
var i = 0;
while (i < c) {
var k = i;
var x = a(start + len - s + k);
do {
x = swap(a, start + k, x);
k = (k + s) % len;
} while (k != i);
i = i + 1;
}
return;
}
The way I solve Scala problems is solving them in Haskell first, and then translating. :)
reorderings xs = take len . map (take len) . tails . cycle $ xs
where len = length xs
This is the easiest way I could think of, which produces the list of all possible shifts, by "shifting left" repeatedly.
ghci> reorderings [1..5]
[[1,2,3,4,5],[2,3,4,5,1],[3,4,5,1,2],[4,5,1,2,3],[5,1,2,3,4]]
The concept is relatively simple (for those comfortable with functional programming, that is). First, cycle the original list, producing an infinite stream from which to draw from. Next, break that stream into a stream of streams, where each subsequent stream has dropped the first element of the previous stream (tails). Next, limit each substream to the length of the original list (map (take len)). Finally, limit the stream of streams to the length of the original list, since there are only len possible reorderings (take len).
So let's do that in Scala now.
def reorderings[A](xs: List[A]):List[List[A]] = {
val len = xs.length
Stream.continually(xs).flatten // cycle
.tails
.map(_.take(len).toList)
.take(len)
.toList
}
We just had to use a small workaround for cycle (not sure if Scala standard libs provide cycle, though I was pleasantly surprised to find they provide tails), and a few toLists (Haskell lists are lazy streams, while Scala's are strict), but other than that, it's exactly the same as the Haskell, and as far as I can tell, behaves exactly the same. You can almost think of Scala's . as behaving like Haskell's, except flowing the opposite way.
Also note this is very nearly the same as dhg's solution, except without the reverses, which (on the upside) makes it more efficient, but (on the downside) provides the cycles in "backwinding" order, rather than "forward" order.
Nice combination of #dhg and #Roman Zykov versions:
scala> val l = List(1,2,3,4,5)
l: List[Int] = List(1, 2, 3, 4, 5)
scala> val re = Stream continually (l ++ l.init sliding l.length) flatten
re: scala.collection.immutable.Stream[List[Int]] = Stream(List(1, 2, 3, 4, 5), ?)
scala> re take 10 foreach println
List(1, 2, 3, 4, 5)
List(2, 3, 4, 5, 1)
List(3, 4, 5, 1, 2)
List(4, 5, 1, 2, 3)
List(5, 1, 2, 3, 4)
List(1, 2, 3, 4, 5)
List(2, 3, 4, 5, 1)
List(3, 4, 5, 1, 2)
List(4, 5, 1, 2, 3)
List(5, 1, 2, 3, 4)
There is a very simple solution:
val orderings = List(1,2,3,4,5)
(orderings ++ orderings.dropRight(1)).sliding(orderings.length).toList
List(List(1, 2, 3, 4, 5), List(2, 3, 4, 5, 1), List(3, 4, 5, 1, 2), List(4, 5, 1, 2, 3), List(5, 1, 2, 3, 4))
My take on it:
#tailrec
def shift(times:Int, data:Array[Int]):Array[Int] = times match {
case t:Int if(t <= 0) => data;
case t:Int if(t <= data.length) => shift(0, (data++data.take(times)).drop(times))
case _ => shift(times % data.length, data);
}
Here's another simple scala solution for shifting a Stream right or left by arbitrary amounts. "Cycle" repeats the stream infintely, then "shift" finds the correct slice. "posMod" allows you to shift by an index larger than xs.length but without actually straying more than xs.length elements in the infinite Stream:
scala> def posMod(a:Int, b:Int) = (a % b + b) % b
scala> def cycle[T](xs : Stream[T]) : Stream[T] = xs #::: cycle(xs)
scala> def shift[T](xs:Stream[T], x: Int) = cycle(xs)
.drop(posMod(x, xs.length))
.take(xs.length)
Then:
scala> shift(Stream(1,2,3,4), 3).toList
--> List[Int] = List(4, 1, 2, 3)
scala> shift(Stream(1,2,3,4), -3).toList
--> List[Int] = List(2, 3, 4, 1)
scala> shift(Stream(1,2,3,4), 30000001).toList
--> List[Int] = List(2, 3, 4, 1)
My proposition:
def circ[A]( L: List[A], times: Int ): List[A] = {
if ( times == 0 || L.size < 2 ) L
else circ(L.drop(1) :+ L.head , times-1)
}
val G = (1 to 10).toList
println( circ(G,1) ) //List(2, 3, 4, 5, 6, 7, 8, 9, 10, 1)
println( circ(G,2) ) //List(3, 4, 5, 6, 7, 8, 9, 10, 1, 2)
println( circ(G,3) ) //List(4, 5, 6, 7, 8, 9, 10, 1, 2, 3)
println( circ(G,4) ) //List(5, 6, 7, 8, 9, 10, 1, 2, 3, 4)
You can instantiate a function that will include the Array(A) and the number of rotation steps that you need(S):
def rotate(A: Array[Int], S: Int): Int = { (A drop A.size - (S % A.size)) ++ (A take A.size - (S % A.size)) }
rotate(Array(1, 2, 3, 4, 5), 1)
Here is one possible solution for sequences
// imports required for: `Scala 2.13.10 (OpenJDK 64-Bit Server VM, Java 1.8.0_292)`
import scala.language.implicitConversions
import scala.language.postfixOps
class ShiftWarper( seq: Seq[ Int ] ) {
def shiftLeft: Seq[ Int ] = if ( seq.isEmpty ) {
seq
} else {
seq.tail :+ seq.head
}
def shiftRight: Seq[ Int ] = if ( seq.isEmpty ) {
seq
} else {
seq.last +: seq.init
}
}
implicit def createShiftWarper( seq: Seq[ Int ] ) =
new ShiftWarper( seq )
def shift_n_Times(
times: Int,
seq: Seq[ Int ],
operation: Seq[ Int ] => Seq[ Int ] ): Seq[ Int ] = if ( times > 0 ) {
shift_n_Times(
times - 1,
operation( seq ),
operation )
} else {
seq
}
// main: unit test
val initialSeq = ( 0 to 9 )
// > val initialSeq: scala.collection.immutable.Range.Inclusive = Range 0 to 9
( initialSeq shiftLeft ) shiftRight
// > val res1: Seq[Int] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
shift_n_Times(
5,
initialSeq,
initialSeq => new ShiftWarper( initialSeq ).shiftRight )
// > val res2: Seq[Int] = Vector(5, 6, 7, 8, 9, 0, 1, 2, 3, 4)