Ruby from two dimension to one dimension array - ruby

I have the following array:
arr = [
"Assignment:Chapter 1 Code Exercises (Real)",
[100, 100, 100, 100, 100, 100, 100, 100],
"Assignment:Chapter 2 Code Exercises (Real)",
[93, 75, 100, 100, 100, 55, 75, 100],
"Assignment:Chapter 3 Code Exercises (Real)",
[100, 80, 100, 100, 90, 85, 65, 100],
"Assignment:Chapter 4 Code Exercises (Real)",
[100, 90, 100, 100, 95, 100, 75, 70],
"Assignment:Chapter 5 Code Exercises (Real)",
[50, 100, 100, 100, 60, 70, 90, 100],
"Assignment:Chapter 6 Code Exercises (Real)",
[0, 85, 100, 100, 60, 85, 70, 85, 100],
"Assignment:Chapter 14 Code Exercises (Real)",
[75, 90, 100, 100, 0, 100, 0, 100],
"Assignment:Chapter 15 Code Exercises (Real)",
[97, 100, 100, 100, 0, 100, 0, 100]
]
I would like to convert this to:
[
["Assignment:Chapter 1 Code Exercises (Real)", 100, 100, 100, 100, 100, 100, 100, 100],
["Assignment:Chapter 2 Code Exercises (Real)", 93, 75, 100, 100, 100, 55, 75, 100],
["Assignment:Chapter 3 Code Exercises (Real)", 100, 80, 100, 100, 90, 85, 65, 100],
["Assignment:Chapter 4 Code Exercises (Real)", 100, 90, 100, 100, 95, 100, 75, 70],
["Assignment:Chapter 5 Code Exercises (Real)", 50, 100, 100, 100, 60, 70, 90, 100],
["Assignment:Chapter 6 Code Exercises (Real)", 0, 85, 100, 100, 60, 85, 70, 85], 100],
["Assignment:Chapter 14 Code Exercises (Real)", 75, 90, 100, 100, 0, 100, 0, 100],
["Assignment:Chapter 15 Code Exercises (Real)", 97, 100, 100, 100, 0, 100, 0, 100]
]
flatten so too "flat". I also tried flatten(1).

array.each_slice(2).map { |(x,y)| [x] + y }
#=> [["Assignment:Chapter 1 Code Exercises (Real)", 100, 100, 100, 100, 100, 100, 100, 100],
# ["Assignment:Chapter 2 Code Exercises (Real)", 93, 75, 100, 100, 100, 55, 75, 100],
# ["Assignment:Chapter 3 Code Exercises (Real)", 100, 80, 100, 100, 90, 85, 65, 100],
# ["Assignment:Chapter 4 Code Exercises (Real)", 100, 90, 100, 100, 95, 100, 75, 70],
# ["Assignment:Chapter 5 Code Exercises (Real)", 50, 100, 100, 100, 60, 70, 90, 100],
# ["Assignment:Chapter 6 Code Exercises (Real)", 0, 85, 100, 100, 60, 85, 70, 85, 100],
# ["Assignment:Chapter 14 Code Exercises (Real)", 75, 90, 100, 100, 0, 100, 0, 100],
# ["Assignment:Chapter 15 Code Exercises (Real)", 97, 100, 100, 100, 0, 100, 0, 100]]

> Hash[*a].map(&:flatten)
=>
[["Assignment:Chapter 1 Code Exercises (Real)", 100, 100, 100, 100, 100, 100, 100, 100],
["Assignment:Chapter 2 Code Exercises (Real)", 93, 75, 100, 100, 100, 55, 75, 100],
["Assignment:Chapter 3 Code Exercises (Real)", 100, 80, 100, 100, 90, 85, 65, 100],
["Assignment:Chapter 4 Code Exercises (Real)", 100, 90, 100, 100, 95, 100, 75, 70],
["Assignment:Chapter 5 Code Exercises (Real)", 50, 100, 100, 100, 60, 70, 90, 100],
["Assignment:Chapter 6 Code Exercises (Real)", 0, 85, 100, 100, 60, 85, 70, 85, 100],
["Assignment:Chapter 14 Code Exercises (Real)", 75, 90, 100, 100, 0, 100, 0, 100],
["Assignment:Chapter 15 Code Exercises (Real)", 97, 100, 100, 100, 0, 100, 0, 100]]
where a is the first array above.
Alternatively, taking #CarySwoveland's recommendation:
a.each_slice(2).map(&:flatten)
is more efficient w/ both time and memory, and doesn't require the strings to be unique.

Related

Recursive Bubble Sort and Insertion Sort in Julia

i´m relatively new to Julia and i´ve implemented the iterative form of the Bubble Sort and Insertion Sort algorithm in Julia.
I would like to know how can i implement the RECURSIVE form Bubble Sort and Insertion Sort in JULIA?
Thank you.
Tail recursion would have helped here:
using BenchmarkTools
function bubblesort(arr::T) where T <: AbstractArray
function recursebubble(a::T, remaining::T, sorted::T)
if length(a) < 2
if isempty(remaining)
return [a ; sorted]
else
x = popfirst!(a)
return recursebubble(remaining, T(), [x ; sorted])
end
else
x = popfirst!(a)
y = popfirst!(a)
if x > y
pushfirst!(remaining, y)
pushfirst!(a, x)
else
pushfirst!(remaining, x)
pushfirst!(a, y)
end
return recursebubble(a, remaining, sorted)
end
end
recursebubble(copy(arr), T(), T())
end
function insertionsort(arr::T) where T <: AbstractArray
function insert(a::T, x::eltype(T))
if isempty(a)
push!(a, x)
else
y = popfirst!(a)
if x <= y
pushfirst!(a, y)
pushfirst!(a, x)
else
a = insert(a, x)
pushfirst!(a, y)
end
end
return a
end
function recursiveinsertion(a::T)
isempty(a) && return a
x = popfirst!(a)
return insert(recursiveinsertion(a), x)
end
return recursiveinsertion(copy(arr))
end
randarray = rand(Int8, 100)
println("Recursive insertion: ", insertionsort(randarray))
#btime insertionsort(randarray)
println("Recursive bubble: ", bubblesort(randarray))
#btime bubblesort(randarray)
println("Base sort: ", sort(randarray))
#btime sort(randarray)
Recursive insertion: Int8[-126, -124, -124, -124, -108, -106, -105, -99, -98, -96, -95, -94, -89, -86, -85, -85, -83, -82, -79, -72, -66, -62, -59, -57, -56, -52, -42, -41, -37, -36, -35, -32, -26, -22, -18, -16, -10, -9, -6, -6, -2, -1, 2, 2, 3, 3, 5, 10, 10, 13, 13, 14, 17, 17, 17, 18, 19, 26, 26, 26, 27, 28, 30, 33, 35, 36, 37, 42, 45, 46, 48, 48, 51, 52, 53, 57, 60, 62, 63, 64, 68, 68, 71, 73, 80, 81, 93, 93, 93, 94, 96, 99, 104, 109, 113, 117, 120, 120, 121, 126]
194.500 μs (6 allocations: 640 bytes)
Recursive bubble: Int8[-126, -124, -124, -124, -108, -106, -105, -99, -98, -96, -95, -94, -89, -86, -85, -85, -83, -82, -79, -72, -66, -62, -59, -57, -56, -52, -42, -41, -37, -36, -35, -32, -26, -22, -18, -16, -10, -9, -6, -6, -2, -1, 2, 2, 3, 3, 5, 10, 10, 13, 13, 14, 17, 17, 17, 18, 19, 26, 26, 26, 27, 28, 30, 33, 35, 36, 37, 42, 45, 46, 48, 48, 51, 52, 53, 57, 60, 62, 63, 64, 68, 68, 71, 73, 80, 81, 93, 93, 93, 94, 96, 99, 104, 109, 113, 117, 120, 120, 121, 126]
391.400 μs (358 allocations: 26.84 KiB)
Base sort: Int8[-126, -124, -124, -124, -108, -106, -105, -99, -98, -96, -95, -94, -89, -86, -85, -85, -83, -82, -79, -72, -66, -62, -59, -57, -56, -52, -42, -41, -37, -36, -35, -32, -26, -22, -18, -16, -10, -9, -6, -6, -2, -1, 2, 2, 3, 3, 5, 10, 10, 13, 13, 14, 17, 17, 17, 18, 19, 26, 26, 26, 27, 28, 30, 33, 35, 36, 37, 42, 45, 46, 48, 48, 51, 52, 53, 57, 60, 62, 63, 64, 68, 68, 71, 73, 80, 81, 93, 93, 93, 94, 96, 99, 104, 109, 113, 117, 120, 120, 121, 126]
847.761 ns (1 allocation: 160 bytes)

Ruby FFI read_array_of_uint8 returns different results for the same read_string

I'm trying to pinpoint a bug we're having and this is as far as I could come.
We're creating a memory pointer which is then filled by a C library:
hash_result_pointer = FFI::MemoryPointer.new(:uint8, 144)
CLibrary(hash_result_pointer)
We're testing this on a macOS High Sierra and on a Ubuntu Xenial via Docker. Here are the outcomes for both:
macOS High Sierra
p hash_result_pointer.read_string
# "\x0F\xE1\x11%\v\xC2)a#"
p hash_result_pointer.read_array_of_uint8(144)
# [15, 225, 17, 37, 11, 194, 41, 97, 64, 0, 32, 156, 191, 7, 38, 254, 119, 123, 104, 145, 2, 160, 137, 112, 10, 193, 71, 15, 3, 134, 245, 5, 6, 24, 234, 1, 100, 4, 188, 45, 158, 28, 120, 130, 42, 62, 152, 15, 1, 97, 48, 16, 0, 41, 125, 5, 4, 20, 142, 3, 10, 3, 156, 1, 65, 10, 122, 15, 52, 67, 52, 109, 38, 13, 18, 128, 47, 44, 53, 90, 23, 72, 32, 82, 56, 17, 42, 126, 57, 71, 71, 80, 9, 180, **65**, 80, 18, 9, 5, 56, 26, 17, 2, 121, 21, 52, 21, 92, 74, 19, 92, 83, 84, 45, 89, 123, 34, 117, 75, 89, 8, 7, 19, 12, 8, 5, 8, 8, 25, 1, 20, 14, 48, 3, 24, 57, 12, 32, 18, 90, 3, 35, 15, 34]
Ubuntu Xenial via Docker
p hash_result_pointer.read_string
# "\x0F\xE1\x11%\v\xC2)a#"
p hash_result_pointer.read_array_of_uint8(144)
# [15, 225, 17, 37, 11, 194, 41, 97, 64, 0, 32, 156, 191, 7, 38, 254, 119, 123, 104, 145, 2, 160, 137, 112, 10, 193, 71, 15, 3, 134, 245, 5, 6, 24, 234, 1, 100, 4, 188, 45, 158, 28, 120, 130, 42, 62, 152, 15, 1, 97, 48, 16, 0, 41, 125, 5, 4, 20, 142, 3, 10, 3, 156, 1, 65, 10, 122, 15, 52, 67, 52, 109, 38, 13, 18, 128, 47, 44, 53, 90, 23, 72, 32, 82, 56, 17, 42, 126, 57, 71, 71, 80, 9, 180, **66**, 80, 18, 9, 5, 56, 26, 17, 2, 121, 21, 52, 21, 92, 74, 19, 92, 83, 84, 45, 89, 123, 34, 117, 75, 89, 8, 7, 19, 12, 8, 5, 8, 8, 25, 1, 20, 14, 48, 3, 24, 57, 12, 32, 18, 90, 3, 35, 15, 34]
As you can see, there is one array element that differs by 1 (65 vs 66) between the two environments. I have no clue why this is happening and I also don't know what could cause this and where shall I look further. Would appreciate any tip!

Even distribution of numbers in array

My problem is that I have a given array of n numbers between 1 and 100. The goal is to pick 5 numbers which result in a minimum total distance. The total distance is calculated by summing up the distance of each number in the initial array to the closest of the 5 picked numbers.
What I (sort of) tried and thought about:
Taking the average number of the array and dividing it by 5 to get something useful?
Dividing the array length by 5, that numbers x and then the first number is array[x] the second one is array[x*2] and so on
Example
Input [5, 10, 15, 20, ..., 85, 90, 95, 100]
Output [10, 30, 50, 70, 90]
(There might be a better output but I hope this makes the goal clear)
As you can see I'm pretty lost and just can't come up with a solution. There probably is a super easy solution to this that I just don't get.
I am just looking for a hint not a solution, I wan't to figure that out myself.
Here is an algorithm that works in polynomial time.
First, sort your array of n things. Next, calculate a 2-dim array which for every 0 <= i <= j < n contains the index of the optimal element to fill the range from the ith element to the jth element. Fill out a similar array of the total distance for each interval from that optimal array.
As an example with the above sample output, the first 2-dim array could look like:
optimal_index = [
[ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9],
[ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10],
[ 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10],
[ 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11],
[ 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11],
[ 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12],
[ 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12],
[ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13],
[ 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13],
[ 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14],
[10, 10, 11, 11, 12, 12, 13, 13, 14, 14],
[11, 11, 12, 12, 13, 13, 14, 14, 15],
[12, 12, 13, 13, 14, 14, 15, 15],
[13, 13, 14, 14, 15, 15, 16],
[14, 14, 15, 15, 16, 16],
[15, 15, 16, 16, 17],
[16, 16, 17, 17],
[17, 17, 18],
[18, 18],
[19],
]
where the index of the optimal element for the range from i to j is at optimal_index[i][j-i]. With the same indexing scheme, the cost matrix would be:
optimal_cost = [
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320, 360, 405, 450, 500],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320, 360, 405, 450],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320, 360, 405],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320, 360],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280, 320],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245, 280],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210, 245],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180, 210],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150, 180],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125, 150],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100, 125],
[ 0, 5, 10, 20, 30, 45, 60, 80, 100],
[ 0, 5, 10, 20, 30, 45, 60, 80],
[ 0, 5, 10, 20, 30, 45, 60],
[ 0, 5, 10, 20, 30, 45],
[ 0, 5, 10, 20, 30],
[ 0, 5, 10, 20],
[ 0, 5, 10],
[ 0, 5],
[ 0],
]
Now what about if we fill ranges with 2 elements? This is a question of taking each range, and looking the costs at each point we could divide it. That new data structure just needs to contain the places to separate between "closest to first element" and "closest to second". From this division we can take any range and quickly divide it into the optimal 2, then tell you what the two selected elements are, and the total cost. This can be filled in with a similar matrix. Note that the previous optimal_cost matrix will make these calculations very straightforward.
Next, what about ranges with 4 elements? This is exactly the same as ranges of 2 elements, except that we are now dividing between the first pair and the second pair. But the logic is the same.
And finally, what about our problem with 5 elements? That's just a question of calculating the optimal division between closest to the first 4 elements and closest to the last one. So just try all of the possibilities.
The natural generalization of this to filling k things in an array of size n is O(n^3 log(k)).

serialize ruby fixnum by denominator into an array

I have a number, say it's 1000000. I want to give a second number, say 100 and create an Array that looks like [0,100,200,300,400....1000000]. I'm having trouble finding a way to iterate in a way that would serialize based on a given denominator. Any ideas?
n = 200
i = 10
(0..n).step(i).to_a
#=> [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120,
# 130, 140, 150, 160, 170, 180, 190, 200]
See Range#step.

What are some algorithms for finding a closed form function given an integer sequence?

I'm looking form a programatic way to take an integer sequence and spit out a closed form function. Something like:
Given: 1,3,6,10,15
Return: n(n+1)/2
Samples could be useful; the language is unimportant.
This touches an extremely deep, sophisticated and active area of mathematics. The solution is damn near trivial in some cases (linear recurrences) and damn near impossible in others (think 2, 3, 5, 7, 11, 13, ....) You could start by looking at generating functions for example and looking at Herb Wilf's incredible book (cf. page 1 (2e)) on the subject but that will only get you so far.
But I think your best bet is to give up, query Sloane's comprehensive Encyclopedia of Integer Sequences when you need to know the answer, and instead spend your time reading the opinions of one of the most eccentric personalities in this deep subject.
Anyone who tells you this problem is solvable is selling you snake oil (cf. page 118 of the Wilf book (2e).)
There is no one function in general.
For the sequence you specified, The On-Line Encyclopedia of Integer Sequences finds 133 matches in its database of interesting integer sequences. I've copied the first 5 here.
A000217 Triangular numbers: a(n) = C(n+1,2) = n(n+1)/2 = 0+1+2+...+n.
0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, 1326, 1378, 1431
A130484 Sum {0<=k<=n, k mod 6} (Partial sums of A010875).
0, 1, 3, 6, 10, 15, 15, 16, 18, 21, 25, 30, 30, 31, 33, 36, 40, 45, 45, 46, 48, 51, 55, 60, 60, 61, 63, 66, 70, 75, 75, 76, 78, 81, 85, 90, 90, 91, 93, 96, 100, 105, 105, 106, 108, 111, 115, 120, 120, 121, 123, 126, 130, 135, 135, 136, 138, 141, 145, 150, 150, 151, 153
A130485 Sum {0<=k<=n, k mod 7} (Partial sums of A010876).
0, 1, 3, 6, 10, 15, 21, 21, 22, 24, 27, 31, 36, 42, 42, 43, 45, 48, 52, 57, 63, 63, 64, 66, 69, 73, 78, 84, 84, 85, 87, 90, 94, 99, 105, 105, 106, 108, 111, 115, 120, 126, 126, 127, 129, 132, 136, 141, 147, 147, 148, 150, 153, 157, 162, 168, 168, 169, 171, 174, 178, 183
A104619 Write the natural numbers in base 16 in a triangle with k digits in the k-th row, as shown below. Sequence gives the leading diagonal.
1, 3, 6, 10, 15, 2, 1, 1, 14, 3, 2, 2, 5, 12, 4, 4, 4, 13, 6, 7, 11, 6, 9, 9, 10, 7, 12, 13, 1, 0, 1, 10, 5, 1, 12, 8, 1, 1, 14, 1, 9, 7, 1, 4, 3, 1, 2, 2, 1, 3, 4, 2, 7, 9, 2, 14, 1, 2, 8, 12, 2, 5, 10, 3, 5, 11, 3, 8, 15, 3, 14, 6, 3, 7, 0, 4, 3, 13, 4, 2, 13, 4, 4, 0, 5, 9, 6, 5, 1, 15, 5, 12, 11, 6
A037123 a(n) = a(n-1) + Sum of digits of n.
0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 46, 48, 51, 55, 60, 66, 73, 81, 90, 100, 102, 105, 109, 114, 120, 127, 135, 144, 154, 165, 168, 172, 177, 183, 190, 198, 207, 217, 228, 240, 244, 249, 255, 262, 270, 279, 289, 300, 312, 325, 330, 336, 343, 351, 360, 370, 381
If you restrict yourself to polynomial functions, this is easy to code up, and only mildly tedious to solve by hand.
Let , for some unknown
Now solve the equations
…
which simply a system of linear equations.
If your data is guaranteed to be expressible as a polynomial, I think you would be able to use R (or any suite that offers regression fitting of data). If your correlation is exactly 1, then the line is a perfect fit to describe the series.
There's a lot of statistics that goes into regression analysis, and I am not familiar enough with even the basics of calculation to give you much detail.
But, this link to regression analysis in R might be of assistance
The Axiom computer algebra system includes a package for this purpose. You can read its documentation here.
Here's the output for your example sequence in FriCAS (a fork of Axiom):
(3) -> guess([1, 3, 6, 10, 15])
2
n + 3n + 2
(3) [[function= -----------,order= 0]]
2
Type: List(Record(function: Expression(Integer),order: NonNegativeInteger))
I think your problem is ill-posed. Given any finite number of integers in a sequence with
no generating function, the next element can be anything.
You need to assume something about the sequence. Is it geometric? Arithmetic?
If your sequence comes from a polynomial then divided differences will find that polynomial expressed in terms of the Newton basis or binomial basis. See this.
There is no general answers; a simple method can be implemented bu using Pade approximants; in two words, assume your sequence is a sequence of coefficients of the Taylor expansion of an unknown function, then apply an algorithm (similar to the continued-fraction algorithm) in order to "simplify" this Taylor-expansion (more precisely: find a rational function very close to the initial (and truncated) function. The Maxima program can do it: look at "pade" on the page: http://maxima.sourceforge.net/docs/manual/maxima_28.html
Another answer tells about the "guess" package in the FriCAS fork of Axiom (see previous answer by jmbr). If I am not wrong; this package is itself inspired from the Rate program by Christian Krattenthaler; you can find it here: http://www.mat.univie.ac.at/~kratt/rate/rate.html Maybe looking at its source could tell you about other methods.

Resources