Related
how to convert Flux<List> into Flux<int[][]>.
I have a Flux<List> -> {1,2,3,.....100} I want to group them by 30 numbers -> [[1,2,3,.....30], [31,32....60],[61.....100]]
I have tried the below approach but was not successful. elements are getting grouped in batches of 5 [ [1,2,3,4,5], [6,7,8,9,10],.....]
Flux<int[][]> groupedData = fluxData.map(x -> {
int outerArraySize = (int) Math.ceil(x.size() / 30) +1;
System.out.println(outerArraySize);
int[][] boxedData = new int[30][outerArraySize];
AtomicInteger innerArray = new AtomicInteger(0);
AtomicInteger outerArray = new AtomicInteger(0);
x.forEach(ids -> {
boxedData[innerArray.get()][outerArray.get()] = ids;
innerArray.getAndIncrement();
if (innerArray.get() == 30) {
innerArray.set(0);
outerArray.getAndIncrement();
}
});
Flux has a useful operator called 'buffer', we can use it to batch the List of Integers.
I have created my 'fluxData' like this, just so I can test my code:
List<Integer> list1 = IntStream.rangeClosed(1, 100).boxed().collect(Collectors.toList());
List<Integer> list2 = IntStream.rangeClosed(1, 40).boxed().collect(Collectors.toList());
List<Integer> list3 = IntStream.rangeClosed(1, 70).boxed().collect(Collectors.toList());
Flux<List<Integer>> fluxData = Flux.just(list1, list2, list3);
Now, we can do the following:
fluxData.map(integersList -> {
List<List<Integer>> batchesList = Flux.fromStream(integersList.stream())
.buffer(30) // This the magic.
.collectList()
.block();
// List<List<Integer>> --> int[][]
int[][] batchesArray = new int[batchesList.size()][];
for(int i = 0;i < batchesArray.length;i++){
batchesArray[i] = new int[batchesList.get(i).size()];
for (int j = 0; j < batchesArray[i].length; j++) {
batchesArray[i][j] = batchesList.get(i).get(j);
}
}
return batchesArray;
})
.subscribe(batchesArray -> System.out.println(Arrays.deepToString(batchesArray)));
Output:
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60], [61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90], [91, 92, 93, 94, 95, 96, 97, 98, 99, 100]]
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [31, 32, 33, 34, 35, 36, 37, 38, 39, 40]]
[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60], [61, 62, 63, 64, 65, 66, 67, 68, 69, 70]]
How can I make an array of 30 min intervals to 8 hours. so this ish:
[30, 60, 90, all-the-way-to, 480]
You can use a Range and the step method, then convert it to an Array:
(30..480).step(30).to_a
The result is:
[30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360, 390, 420, 450, 480)
Your arguments are
increment = 30
duration = 480 # 8*60
You could use
increment.step(by: increment, to: duration).to_a
#=> [ 30, 60, 90, 120, 150, 180, 210, 240,
# 270, 300, 330, 360, 390, 420, 450, 480]
which reads well. Numeric#step, when used without a block, returns an enumerator, which is why .to_a is needed.
I came up with this, but #infused answer is way better.
a = (1..16).to_a.map{|i| i*30 }
Option selecting (Enumerable#select) from the range:
stop = 480
step = 30
(step..stop).select { |n| n % step == 0 }
#=> [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360, 390, 420, 450, 480]
Hello I am having trouble encrypting using an array as the key and the value with the ruby-mcrypt gem. The gem lets me use an array for the key fine, cipher = Mcrypt.new("rijndael-256", :ecb, secret) works. But it will give me an error when I try to encrypt. I've tried many things but no luck. Does anyone know if Mcrypt just doesn't like encrypting with an array?
require 'mcrypt'
def encrypt(plain, secret)
cipher = Mcrypt.new("rijndael-256", :ecb, secret)
cipher.padding = :zeros
encrypted = cipher.encrypt(plain)
p encrypted
encrypted.unpack("H*").first.to_s.upcase
end
array_to_encrypt = [16, 0, 0, 0, 50, 48, 49, 55, 47, 48, 50, 47, 48, 55, 32, 50, 50, 58, 52, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
key_array = [65, 66, 67, 68, 49, 50, 51, 52, 70, 71, 72, 73, 53, 54, 55, 56]
result = encrypt(array_to_encrypt, key_array)
p "RESULT IS #{result}"
The output is as follows:
Mcrypt::RuntimeError: Could not initialize mcrypt: Key length is not legal.
I traced this error to here in the ruby-mcrypt gem but don't understand it enough to figure out why I am getting the error message. Any help or insights would be amazing. Thanks!
The library doesn't support arrays. You'll need to use Strings instead:
def binary(byte_array)
byte_array.pack('C*')
end
array_to_encrypt = [16, 0, 0, 0, 50, 48, 49, 55, 47, 48, 50, 47, 48, 55, 32, 50, 50, 58, 52, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
key_array = [65, 66, 67, 68, 49, 50, 51, 52, 70, 71, 72, 73, 53, 54, 55, 56]
result = encrypt(binary(array_to_encrypt), binary(key_array))
p "RESULT IS #{result}"
I want to add an array to a two dimensional array like this:
arrays = [[8300, 6732, 4101, 3137, 3097], [1088, 647, 410, 138, 52], [623, 362, 191, 25, 0]]
new_array = [10, 100, 1000]
arrays.map.with_index{|v,i| v << new_array[i]}
# => [[8300, 6732, 4101, 3137, 3097, 10], [1088, 647, 410, 138, 52, 100], [623, 362, 191, 25, 0, 1000]]
It works well, but I want to know if there is more simpler way to accomplish this behavior.
I appreciate any suggestion.
arrays.zip(new_array).map(&:flatten)
# => [[8300, 6732, 4101, 3137, 3097, 10], [1088, 647, 410, 138, 52, 100], [623, 362, 191, 25, 0, 1000]]
You can use zip:
arrays.zip(new_array).each { |arr, item| arr << item }
arrays
# => [[8300, 6732, 4101, 3137, 3097, 10], [1088, 647, 410, 138, 52, 100], [623, 362, 191, 25, 0, 1000]]
Just a little extension to Santosh answer. If there are nested arrays and you want to the result to be as nested as in original arrays like
arrays = [[8300, [6732], 4101, [3137], 3097], [1088, [647], 410, 138, 52], [623, [362], 191, 25, 0]]
new_array = [10, [100], 1000]
required_answer = [[8300, [6732], 4101, [3137], 3097, 10], [1088, [647], 410, 138, 52, 100], [623, [362], 191, 25, 0, 1000]]
then you can use
arrays.zip(new_array).map{|x| x.flatten(1)}
this will flatten the array to one level.
Hi I'm trying to write some simple code to use random mutation hill climbing for the travelling salesman problem. I have created a Tour class as such:-
import java.util.ArrayList;
import java.util.Collections;
public class Tour
{
private ArrayList<Integer> tour;
// Specified tour
public Tour(ArrayList<Integer> tour) { this.tour = tour; }
// Random tour
public Tour(int size)
{
// Initalize tour with size
tour = new ArrayList<Integer>(size);
// Add integers up to size into ArrayList
for (int i=0; i<size; ++i) {tour.add(i);}
// Shuffle ArrayList
Collections.shuffle(tour);
}
ArrayList<Integer> getTour() {return tour;}
void printTour()
{
for (int i=0; i<tour.size(); ++i)
{
System.out.print(tour.get(i) + ", ");
}
}
// Get the distance between all tour stops using a set of distances
double getFitness (double[][] distances)
{
double s = 0;
for (int i=0; i<tour.size()-1; ++i)
{
int a = tour.get(i);
int b = tour.get(i+1);
s += distances[a][b];
}
int start_city = tour.get(0);
int end_city = tour.get(tour.size()-1);
s += distances[end_city][start_city];
return s;
}
// Makes a small change to the tour
void smallChange()
{
// Change random index values to swap
int indexfirst = CS2004.UI(0, tour.size()-1);
int indexsecond = CS2004.UI(0, tour.size()-1);
// Checks to make sure index values are not the same
while (indexsecond == indexfirst)
{
indexsecond = CS2004.UI(0, tour.size()-1);
}
// Store city value in temp variable
int indexTemp = tour.get(indexfirst);
// Swap values
tour.set(indexfirst, tour.get(indexsecond));
tour.set(indexsecond, indexTemp);
}
}
My RMHC method looks like this:-
public static Tour RMHC(double[][] distances, int iter)
{
Tour sol = new Tour(distances.length);
double oldFitness;
double fitness = 0;
Tour oldSol=null;
for (int i=0;i<iter;i++)
{
oldSol = null;
// Make old solution equal to solution before change
oldSol = new Tour(sol.getTour());
System.out.println(oldSol.getTour());
// Calculate old fitness for comparison
oldFitness = sol.getFitness(distances);
// Change solution slightly
sol.smallChange();
// Calculate new fitness
fitness = sol.getFitness(distances);
/* Compare new fitness to old fitness
* set solution back to old solution and fitness to old fitness if
* new solution is not better */
System.out.println(oldFitness + " " + fitness);
if (fitness > oldFitness) {System.out.println(oldSol.getTour()); System.out.println(sol.getTour()); sol = null; sol = new Tour(oldSol.getTour()); fitness = oldFitness;}
// Print iteration number and new fitness
System.out.println("Iteration " + (i+1) + ", fitness: " + sol.getFitness(distances));
}
return(sol);
}
The problem I'm having is that when I call my smallChange method in the RMHC it seems to change the Tour for both the old solution and the new solution. I ran this for a few iterations on a 48 size dataset and got the following output:-
[11, 6, 13, 37, 23, 45, 34, 25, 16, 39, 5, 35, 31, 9, 27, 0, 10, 42, 30, 28, 4, 12, 33, 36, 2, 21, 17, 29, 18, 20, 32, 3, 15, 47, 26, 19, 46, 8, 22, 44, 7, 24, 43, 14, 41, 1, 38, 40]
155843.9387676824 159088.1701641078
[31, 6, 13, 37, 23, 45, 34, 25, 16, 39, 5, 35, 11, 9, 27, 0, 10, 42, 30, 28, 4, 12, 33, 36, 2, 21, 17, 29, 18, 20, 32, 3, 15, 47, 26, 19, 46, 8, 22, 44, 7, 24, 43, 14, 41, 1, 38, 40]
[31, 6, 13, 37, 23, 45, 34, 25, 16, 39, 5, 35, 11, 9, 27, 0, 10, 42, 30, 28, 4, 12, 33, 36, 2, 21, 17, 29, 18, 20, 32, 3, 15, 47, 26, 19, 46, 8, 22, 44, 7, 24, 43, 14, 41, 1, 38, 40]
Iteration 1, fitness: 159088.1701641078
[31, 6, 13, 37, 23, 45, 34, 25, 16, 39, 5, 35, 11, 9, 27, 0, 10, 42, 30, 28, 4, 12, 33, 36, 2, 21, 17, 29, 18, 20, 32, 3, 15, 47, 26, 19, 46, 8, 22, 44, 7, 24, 43, 14, 41, 1, 38, 40]
159088.1701641078 144709.1336957683
Iteration 2, fitness: 144709.1336957683
[31, 6, 13, 37, 7, 45, 34, 25, 16, 39, 5, 35, 11, 9, 27, 0, 10, 42, 30, 28, 4, 12, 33, 36, 2, 21, 17, 29, 18, 20, 32, 3, 15, 47, 26, 19, 46, 8, 22, 44, 23, 24, 43, 14, 41, 1, 38, 40]
144709.1336957683 143387.5110957744
Iteration 3, fitness: 143387.5110957744
[31, 6, 13, 37, 7, 45, 22, 25, 16, 39, 5, 35, 11, 9, 27, 0, 10, 42, 30, 28, 4, 12, 33, 36, 2, 21, 17, 29, 18, 20, 32, 3, 15, 47, 26, 19, 46, 8, 34, 44, 23, 24, 43, 14, 41, 1, 38, 40]
143387.5110957744 143565.3842060348
[31, 6, 13, 37, 7, 45, 22, 25, 16, 39, 5, 35, 14, 9, 27, 0, 10, 42, 30, 28, 4, 12, 33, 36, 2, 21, 17, 29, 18, 20, 32, 3, 15, 47, 26, 19, 46, 8, 34, 44, 23, 24, 43, 11, 41, 1, 38, 40]
[31, 6, 13, 37, 7, 45, 22, 25, 16, 39, 5, 35, 14, 9, 27, 0, 10, 42, 30, 28, 4, 12, 33, 36, 2, 21, 17, 29, 18, 20, 32, 3, 15, 47, 26, 19, 46, 8, 34, 44, 23, 24, 43, 11, 41, 1, 38, 40]