Is there a Smalltalk way to transposing an Array? - collections

Suppose I have an array which looks like this
{ { #a . #b . #c } .
{ #e . #f . #g } }.
Is there a quick way to turn this into
{ { #a . #e } . { #b . #f } . { #c . #g } }
the code should work for n-element subarrays too.
{ { #a . #b . #c . #d } .
{ #e . #f . #g . #h } }.

{ #a . #b . #c } with: { #e . #f . #g } collect: [ :each1 :each2 | { each1 . each2 } ]
will give you
#(#(#a #e) #(#b #f) #(#c #g))

General purpose one liner, no assumptions about column or row count.
(1 to: rows first size) collect: [:column | rows collect: [:row | row at: column]]
Some Smalltalk's even implement:
SequenceableCollection>>keys
^1 to: self size
In that case the first can be even nicer implemented as:
rows first keys collect: [:column | rows collect: [:row | row at: column]]

Not quite elegant but it works for collections of any size in almost every Smalltalk:
| results input |
input := { { #a . #b . #c } .
{ #e . #f . #g } }.
results := Array new: input first size.
1 to: results size do: [ : subIndex |
results at: subIndex put: (input collect: [ : sub | sub at: subIndex ]) ].
results

If you are dealing with matrices, I would suggest creating the Matrix class along with this instance creation method (class side):
Matrix class >> fromBlock: aBlock numRows: n columns: m
| matrix |
matrix := self newRows: n columns: m.
1 to: n do: [:i |
1 to: m do: [:j | | aij |
aij := aBlock value: i value: j.
matrix atRow: i column: j put: aij]].
^matrix
Then, given a matrix you would transpose it using this method (instance side):
Matrix >> transposed
^self class
fromBlock: [:i :j | self atRow: j column: i]
numRows: self numColumns
columns: self numRows

Related

Invalid_argument "String.sub / Bytes.sub"

I have a small problem on an exercice that i'm doing.
I try to recursively count vowels in a String but i have this strange error popping.
Can someone explain me why ?
let rec nb_voyelle = function chaine ->
if chaine == "" then
0
else
let length = (String.length chaine)-1 in
let p_length = String.sub chaine 0 length in
match chaine.[length] with
| 'a' | 'e' | 'i' | 'o' | 'u' | 'y' -> 1 + nb_voyelle p_length
| _ -> 0 + nb_voyelle p_length
;;
Answer is i used "==" to compare the string in my final case which is not the good pervasive to test equality between two elements.
As such, the case (String.sub "" 0 -1) happens and the function fail raising this error.

Vector of strings reports the error "str does not have a constant size known at compile time"

When trying to print out the contents of a multidimensional vector in Rust, it seems as though you cannot use the type Vec<Vec<str>> for the vector.
fn print_multidimensional_array(multi: &Vec<Vec<str>>) {
for y in 0..multi.len() {
for x in 0..multi[y].len() {
print!("{} ", multi[y][x]);
}
println!("");
}
}
With this code, I get the output:
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> src/main.rs:1:1
|
1 | / fn print_multidimensional_array(multi: &Vec<Vec<str>>) {
2 | | for y in 0..multi.len() {
3 | | for x in 0..multi[y].len() {
4 | | print!("{} ", multi[y][x]);
... |
7 | | }
8 | | }
| |_^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: required by `std::vec::Vec`
What type of vector could I use for this to work?
Use Vec<Vec<&str>>.
fn print_multidimensional_array(multi: &[Vec<&str>]) {
for y in multi {
for v in y {
print!("{} ", v);
}
println!();
}
}
fn main() {
let v = vec![vec!["a", "b"], vec!["c", "d"]];
print_multidimensional_array(&v);
}
See also:
What does “`str` does not have a constant size known at compile-time” mean, and what's the simplest way to fix it?
What does "Sized is not implemented" mean?
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?
Passing Vec<String> as IntoIterator<&'a str>
What are the differences between Rust's `String` and `str`?
Because I like to make things overly generic...
fn print_multidimensional_array<I>(multi: I)
where
I: IntoIterator,
I::Item: IntoIterator,
<I::Item as IntoIterator>::Item: AsRef<str>,
{
for y in multi {
for v in y {
print!("{} ", v.as_ref());
}
println!();
}
}
fn main() {
let v1 = vec![vec!["a", "b"], vec!["c", "d"]];
let v2 = vec![["a", "b"], ["c", "d"]];
let v3 = [vec!["a", "b"], vec!["c", "d"]];
let v4 = [["a", "b"], ["c", "d"]];
print_multidimensional_array(&v1);
print_multidimensional_array(&v2);
print_multidimensional_array(&v3);
print_multidimensional_array(&v4);
}

TCL recursively call procedure

I'm a beginner at TCL and while trying to build the GCD algorithm I ran into some problems I'd like some help with:
how can I call a proc inside a proc recursively like so
proc Stein_GCD { { u 0 } { v 0 } } {
if { $v == 0 } {
puts "$u\t\t$v\t\t$v"
}
if { [expr { $v % 2 } && { $u % 2 } ] == 0 } {
return [expr 2 * ${Stein_GCD 1 0} ]
}
}
set a [Stein_GCD 2 2 ]
puts $a
as you can see, I made the proc to evaluate GCD(the code does not make any sense because I'm trying to solve an example issue), and I'm trying to recursively call the proc again to continue evaluating(notice that I made an if statement that can understand the Stein_GCD 1 0 call, yet the tcl 8.6.6 online EDA emulator says:
can't read "Stein_GCD 1 0": no such variable
while executing
"expr 2 * ${Stein_GCD 1 0} "
(procedure "Stein_GCD" line 5)
invoked from within
"Stein_GCD 2 2 "
invoked from within
"set a [Stein_GCD 2 2 ]"
(file "main.tcl" line 7)
Can you tell me how to efficiently recursively call a proc, and where was my mistake?
will gladly provide more info in the case I did a bad job at explaining.
The error can't read "Stein_GCD 1 0": indicates that you are treating the data as a single string instead of separate arguments. The problem line:
return [expr 2 * ${Stein_GCD 1 0} ]
is not written correctly. ${Stean_GCD 1 0} is not a variable.
You should have:
return [expr 2 * [Stein_GCD 1 0] ]
You want the result from Stein_GCD 1 0, so the brackets should be used.

Cumulative sum in jq

I have a series of [timestamp, count] pairs in an array and a want to compute the cumulative sum at each timestamp using jq. How could I do that?
Here a sample data set:
[
[1431047957699, 1],
[1431047958269, 1],
[1431047958901, 1],
[1431047959147, -1],
[1431047960164, 1]
]
And the expected result:
[1431047957699, 1],
[1431047958269, 2],
[1431047958901, 3],
[1431047959147, 2],
[1431047960164, 3]
Is it possible to do this with jq?
The following is quite general (e.g. it can be used with an array of objects):
def accumulate(f):
reduce .[1:][] as $row
([.[0]];
. as $x
| $x + [ $row | (f = ($x | .[length-1] | f) + ($row|f) ) ] );
accumulate(.[1])
If you are using a sufficiently recent version of jq, then "$x |
.[length-1]" can be simplified to "$x[-1]".
Solution using foreach
If your jq has foreach, then the following variant can be used. It would be particularly appropriate if a stream of values rather than array is wanted.
def accumulates(f):
foreach .[] as $row
(0;
. + ($row | f) ;
. as $x | $row | (f = $x));
Usage:
For a stream: accumulates(.[0])
For an array: [accumulates(.[0])
Take a functional approach to this and create an update function that will create the updated values with the cumulative sum.
def accumulate(acc):
select(length > 0) |
(.[0][1] + acc) as $next |
(.[0] | .[1] = $next), (.[1:] | accumulate($next))
;
[accumulate(0)]
Here, we break the array into "head" and "tail" updating the head with the current sum and recursively update the tail. The results are placed back into a new array.

Multiple if statement in loop condition

I am a Phd student in the university of Padua and I am trying to write a little script (the first!) in R cran v. 3.0.1 to make a simulation on epidemiology.
I'd like to change the values of a vector of 883 values basing on a neighbour matrix constructed with nb2mat from a shapefile: if i and j (two cells) are neighbour (matrix) and i or j have a positive value in the vector, I'd like to transform the value of both i and j to 1 (positive), otherwise the value of i and j should remain 0. When I launch the next little script:
for(i in 1:883)
{ for(j in 1:883)
{ if(MatriceDist[i,j] > 0 & ((vectorID[i] > 0 | vectorID[j] > 0)) {
vectorID[i] = 1 & vectorID[j] = 1
print(vectorID)
} } }
the answer from the software is:
Error: unexpected '{' in:
" { for(j in 1:883)
{ while(MatriceDist[i,j] > 0 & ((vectorID[i] > 0 | vectorID[j] > 0)) {"
I think that it is an error in the statement for if but I can not understand how to solve it...
Thank you everyone!
Elisa
check your brackets :-)
for(i in 1:883) {
for(j in 1:883) {
if(MatriceDist[i,j] > 0 & (vectorID[i] > 0 | vectorID[j] > 0)) { vectorID[i] = 1 & vectorID[j] = 1 print(vectorID)
}
}
}
you had one ( to mucch before vectorID in your if statement.
please double check is the condition now specified in the statement is still the one you require.
btw: for loops are very slow in R. If you know the end size of vectorID, try pre-allocating the full matrix. That will speed things up a little bit.

Resources