I have 2 lists:
alist: [a b c d]
blist: [1 2 3 4]
(In reality they are long lists). How can I assign variables in alist to corresponding values in blist in one go? Hence a becomes 1, b becomes 2 and so on.
I tried:
foreach i alist j blist [i: j]
But it give following error:
*** Script Error: j has no value
*** Where: foreach
*** Stack:
I also tried:
i: 1
while [true] [
if i > (length? alist) [break]
alist/i: blist/i
i: i + 1
]
But it also does not work:
*** Script Error: cannot set none in path alist/i:
*** Where: set-path
*** Stack:
alist/i and blist/i return none (on checking with print command).
Similar question are there for other languages also, e.g.: Parallel array assignment in PHP and Parallel assignment in Java? . Thanks for your help.
easy way, set one list to the other
>> set alist blist
== [1 2 3 4]
>> a
== 1
>> b
== 2
>> c
== 3
>> d
== 4
>> alist
== [a b c d]
>> reduce alist
== [1 2 3 4]
>> get alist/1
== 1
and the cumbersome way
>> forall alist [alist/1: blist/(index? alist) ]
>> i: 2
== 2
>> get alist/:i
== 2
Related
I have just started learning Haskell and I am trying to write some basic functions in order to get a better understanding of this language.
I want to write a function which takes a list and an Int (N) as argument and returns the element at index N in the list, without using the !! operator or any built-in function.
Here is what I tried :
myHead :: [a] -> a
myHead (x:_) = x
myHead [] = error "head: empty list"
myNth :: [a] -> Int -> a
myNth x i = if i < 0
then error "nth: index can't be negative"
else myNthIterator x i 0
myNthIterator :: [a] -> Int -> Int -> a
myNthIterator [] i n = error "nth: bad index"
myNthIterator (_:x) i n = if i == n
then myHead x
else myNthIterator x i ( n + 1 )
It works but it's shifted to the right. For example myNth [1, 2, 3, 4] 2 would give 4 and not 3.
From what I understand, (_:x) removes the first element of the list and I don't see how to iterate through the list element by element.
Could someone put me on the trail? I find it difficult to find resources for beginners in this language.
We can use Maybe to model whether the index was valid.
nth :: Int -> [a] -> Maybe a
nth 0 (x : _) = Just x
nth n (x : xs) = nth (n - 1) xs
nth _ [] = Nothing
We can pattern match on the index to get our base case, and the list to get the first element and tail.
What you're doing there with (_:x) is called "pattern matching" in case you didn't know. The general pattern for iterating through a list would be (x : xs) where x is head element of the list being matched and xs is the rest of the list. If you use _ you don't remove anything it is still matched to _ which is the convention for saying "I won't use this".
With that you can make a function like this:
myNth :: [a] -> Int -> a
myNth [] _ = error "out of range"
myNth (x : xs) 0 = x
myNth (_ : xs) n = myNth xs (n - 1)
Whenever myNth is called it will go top to bottom over those definitions trying to match the patterns to the input. So when you call myNth [10,11] 1 it won't match the first clause because [10,11] doesn't match an empty list, it won't match the second either because 1 is not 0 and so it will match the third case where it will match the [10,11] on (10 : [11]), therefore _ is 10 and xs is [11] and 1 will be matched as n. Then it calls itself recursively, as myNth [11] 0. Now that will match the second case and it will return x from the match of [11] on (11 : [])
Like 414owen said you can use the Maybe a type to avoid using error.
P.S.: I don't know how beginner you are but I assume you know of the : operator, it prepends an element to a list... If you go more in depth (afaik) every list is actually stored as a sequence of a:(b:(c:(d:(e:[])))) which is equivalent to [a,b,c,d,e] which is equivalent to a:[b,c,d,e] etc.
It works but it's shifted to the right. For example myNth [1, 2, 3, 4] 2 would give 4 and not 3.
myNthIterator (_:x) i n = if i == n
then myHead x
else myNthIterator x i ( n + 1 )
Let us look at myNthIterator [1..4] 1 1
myNthIterator [1..4] 1 1 -- replace [a, b] with (a: (b : []))
== myNthIterator (1 : [2, 3, 4]) 1 1
-- matching with `myNthIterator (_:x) i n` will result in
-- 1 ~ _
-- x ~ [2, 3, 4]
-- i ~ 1
-- n ~ 1
== if 1 == 1 then myHead [2, 3, 4] else myNthIterator [2, 3, 4] 1 (1 + 1)
== myHead [2, 3, 4]
== 2
So (_:x) matching against (1 : [2, 3, 4]) is suspicious. A first step in fixing it is to replace (_:x) by (x:xs).
myNthIterator (x:xs) i n = ...
In our example this would mean x == 1 and xs == [2, 3, 4].
new to Ocaml. I've no clue what is happening here and I've been trying to solve this for maybe 2 hours.
Here is the code:
let hailstorm n =
match n with
| (mod n 2 == 0) -> (n/2)
| (mod n 2 == 1) -> (3*n+1);;
When I try to compile it says:
File "./x.ml", line 3, characters 11-12:Error: Syntax error: ')' expected
File "./x.ml", line 3, characters 6-7:
Error: This '(' might be unmatched
The keyword mod is a binary operator (like lsl, lsr, asr, land, lor, lxor and or) . For instance,
let zero = 2 mod 2
Binary operator can be transformed into standard function by wrapping them around parentheses,
let zero = (mod) 2 2
this is why the parser is expecting a closing parenthesis after (mod .
Then, you pattern matching is wrong because n mod 2 == 0 is an expression, not a pattern (and you should use structural equality = rather than physical equality ==):
let f n = match n mod 2 with
| 0 -> ...
| _ -> ...
or
let f n = match n mod 2 = 0 with
| true -> ...
| false -> ...
which is probably simpler with an if ... then ... else ... .
I want to alter a series of variables from a loop, but the following code is not working:
a: 10
b: 20
c: 30
print reduce [a b c] ; output is 10 20 30 as expected
varnames: [a b c] ; make a series of variables
foreach i varnames [ ; loop to convert each to 0
i: 0
]
print "After conversion loop: "
print reduce [a b c] ; values are still 10 20 30 (expected 0 0 0)
After running this code, I'd expect the values of a, b, c to be changed, but they're not:
>> print reduce [a b c]
10 20 30
Where is the problem?
>> set varnames: [a b c] [10 20 30]
== [10 20 30]
>> foreach i varnames [set i 0]
== 0
>> reduce varnames
== [0 0 0]
You've given i a value from the loop, and then given it a different value of 0, but you actually haven't altered the word that i referred to. set allows you to do this.
one more, but shortest solution
>> set [a b c] 0
== 0
>> reduce [a b c]
== [0 0 0]
one more
set set 'varnames [a b c] [0]
>> print probe varnames
[a b c]
0 0 0
I want to get values from 2 series into one but it is not working:
I have 2 series:
a: [1 2 3]
b: [4 5 6 7]
I want to get all values in one list, so that I can access them as allv/1, allv/2... allv/7.
Following is not working since it makes a series of series and not series of values:
allv: [a b]
print allv ; => prints all 6 values, but following do not work:
print allv/1 ; => gives a (desired is 1)
print allv/2 ; => gives b (desired is 2)
print allv/3 ; => gives none (desired is 3)
I tried following function to combine values in one series:
mycombine: function [ll][
temp: []
foreach l ll [
repeat i length? l [
temp: append temp l/:i ] ]
temp]
mycombine [a b]
But above gives error:
*** Script Error: length? does not allow word! for its series argument
*** Where: length?
*** Stack: rncombine
The series has got converted into word and is not working.
How can I solve this?
Just append
a: [1 2 3]
b: [4 5 6 7]
c: [8 9 10]
d: [11 12 13 14]
>> allv: append a b
== [1 2 3 4 5 6 7]
>> a
== [1 2 3 4 5 6 7]
does what you want. But beware even a contains all values, as you have appendend the values of b to the block a. If you want a new block you have to use
allv: append copy a b
If you want to append more series you can do
>> foreach x [a b c d] [ append [] reduce x]
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14]
Instead of reduce also get x is working.
Another way of combining
>> compose [(a) (b) (c)]
== [1 2 3 4 5 6 7 8 9 10 ]
Suppose I have the following nested list:
list =
[[0, 1, 0],
[1, 9, 1],
[1, 1, 0]]
Assuming you are only given the x and y coordinate of 9. How do I use Haskell code to find out how many 1's surrounds the number 9?
Let me clarify a bit more, assume the number 9 is positioned at (0, 0).
What I am trying to do is this:
int sum = 0;
for(int i = -1; i <= 1; i++){
for(int j = -1; j <= 1; j++){
if(i == 0 || j == 0) continue;
sum += list[i][j];
}
}
The positions surrounding (0,0) are the following coordinates:
(-1, -1) (0, -1) (1, -1)
(-1, 0) (1, 0)
(-1, 1) (0, 1) (1, 1)
list = [[0,1,0],[1,9,1],[1,1,0]]
s x y = sum [list !! j !! i | i <- [x-1..x+1], j <- [y-1..y+1], i /= x || j /= y]
--s 1 1 --> 5
Note that I there is no error correction if the coordinates are at the edge. You could implement this by adding more conditions to the comprehension.
A list of lists isn't the most efficient data structure if things get bigger. You could consider vectors, or a Map (Int,Int) Int (especially if you have many zeros that could be left out).
[Edit]
Here is a slightly faster version:
s x y xss = let snip i zs = take 3 $ drop (i-1) zs
sqr = map (snip x) $ snip y xss
in sum (concat sqr) - sqr !! 1 !! 1
First we "snip out" the 3 x 3 square, then we do all calculations on it. Again, coordinates on the edges would lead to wrong results.
Edit: switched to summing surrounding 8 rather than surrounding 4
How often do you just want the surrounding count for just one entry? If you want it for all the entries, lists still perform fairly well, you just have to look at it holistically.
module Grid where
import Data.List (zipWith4)
-- given a grid A, generate grid B s.t.
-- B(x,y) = A(x-1,y-1) + A(x,y-1) + A(x+1,y-1)
-- + A(x-1,y) + A(x+1,y)
-- + A(x-1,y+1) + A(x,y+1) + A(x+1,y+1)
-- (where undefined indexes are assumed to be 0)
surrsum :: [[Int]] -> [[Int]]
surrsum rs = zipWith3 merge rs ([] : init rs') (tail rs' ++ [[]])
where -- calculate the 3 element sums on each row, so we can reuse them
rs' = flip map rs $ \xs -> zipWith3 add3 xs (0 : xs) (tail xs ++ [0])
add3 a b c = a+b+c
add4 a b c d = a+b+c+d
merge [] _ _ = []
-- add the left cell, right cell, and the 3-element sums above and below (zero-padded)
merge as bs cs = zipWith4 add4 (0 : init as) (tail as ++ [0]) (bs ++ repeat 0) (cs ++ repeat 0)
-- given a grid A, replace entries not equal to 1 with 0
onesOnly :: [[Int]] -> [[Int]]
onesOnly = map . map $ \e -> if e == 1 then 1 else 0
list :: [[Int]]
list = [[0, 1, 0]
,[1, 9, 1]
,[1, 1, 0]]
Now you can drop down to ghci to see it work:
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) list
0 1 0
1 9 1
1 1 0
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) $ onesOnly list
0 1 0
1 0 1
1 1 0
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) . surrsum $ onesOnly list
2 2 2
3 5 2
2 3 2