For example if we have two strings "abc" and "1234" i want result "abc4" (the first string masks second). (If we draw them vertical it's like a wave comes from left and tuch chars)
"a" "1" "a"
wave -> "b" "2" result "b"
"c" "3" "c"
"4" "4"
I start with this solution with Haskell
slice from to xs = take (to - from + 1) (drop from xs)
merge l1 l2 = if length l2 > length l1
then l1 ++ slice (length l1) (length l2) l2
else l1
Can you please provide some more elegant\compact solutions.
You just need a special merge function
> let merge [] ys = ys
| merge xs [] = xs
| merge (x:xs) (y:ys) = x : merge xs ys
or using drop
> let merge2 x y = x ++ drop (length x) y
You want kind of a "zipLongest", and transpose is kind of like that:
maskMerge1 :: [b] -> [b] -> [b]
maskMerge1 as bs = map head $ transpose [as,bs]
-- or:
-- head <$> transpose [as,bs]
This is pretty compact and elegant (with big thanks to #leftaroundabout for the comments!).
Looking from above,
[ "abc" , [ ['a' ,'b' ,'c' ] ,
"1234" ] ['1' ,'2' ,'3' ,'4'] ]
---------- --------------------------
[ "a1","b2","c3","4" ] -- transpose
---------- --------------------------
"abc4" [ 'a' ,'b' ,'c' ,'4' ] -- map head
The code with length in the other answer also works, and even for an infinite x despite calling the dreaded length on it, but it will retain the whole of x in memory because of calling the length on it.
How can i get the freq of consecutive numbers in a list in Netlogo?
For example, if my list is:
list = [1 1 1 0 0 1 1 0 1 1 0 0 0 ]
Then the output should look as follows:
output = [3 2 2 1 2 3]
I have decided that this is a job for recursion:
to-report count-consecutive-items [ xs ]
report count-consecutive-items-loop [] nobody xs
end
to-report count-consecutive-items-loop [ counts-so-far last-item remaining-items ]
report ifelse-value (empty? remaining-items) [
; no more items to count, return the counts as they are
counts-so-far
] [
(count-consecutive-items-loop
(ifelse-value (first remaining-items = last-item) [
; this is the same item as the last,
ifelse-value (empty? counts-so-far) [
; if our list of counts is empty, start a new one
[1]
] [
; add one to the current count and keep going
replace-item (length counts-so-far - 1) counts-so-far (1 + last counts-so-far)
]
] [
; this is an item we haven't seen before: start a new count
lput 1 counts-so-far
])
(first remaining-items)
(but-first remaining-items)
)
]
end
to test
let result count-consecutive-items [1 1 1 0 0 1 1 0 1 1 0 0 0]
print result
print result = [3 2 2 1 2 3]
end
I'm sure that someone else can come up with a nice imperative version that will be much easier to understand than this, but you can consider this as a pedagogical exercise: if you manage to understand this code, it will help you on your way to NetLogo enlightenment.
to-report countRuns [#lst]
if 0 = length #lst [report #lst]
let val first #lst
let _ct 1
let cts []
foreach butfirst #lst [? ->
ifelse ? = val [
set _ct (1 + _ct)
][
set cts lput _ct cts
set val ?
set _ct 1
]
]
report lput _ct cts
end
I was playing around a bit in Haskell to get familiar with it, but got stuck at the following problem:
I want to define a function that, given a list containing some amount of other lists, each containing 0 or more tuples, creates a new list as following:
*Main> foo
[
[ (1,2), (3,4) ],
[ (5,6) ],
[ (7,8), (9,10) ]
]
= [
[ (1,2), (5,6), (7,8) ],
[ (1,2), (5,6), (9,10) ],
[ (3,4), (5,6), (7,8) ],
[ (3,4), (5,6), (9,10) ]
]
So, in other words, the function should compose a list with every tuple from the first list combined with in each case one of the other tuples in the N remaining lists.
I was trying to write a recursive algorithm for this, but can't wrap my head around dealing with the N amount of other lists to combine tuples with. For just two lists of tuples, I would write something like:
composeList [] _ = []
composeList (x:xs) list = composeTuples x list ++ composeList xs list
composeTuples _ [] = []
composeTuples t (x:xs) = [t,x] : composeTuples t xs
This gives me:
*Main Data.List> composeList [(1,2),(3,4)] [(5,6),(7,8)]
[
[ (1,2), (5,6) ],
[ (1,2), (7,8) ],
[ (3,4), (5,6) ],
[ (3,4), (7,8) ]
]
Though I can't seem to put the pieces together and make it work for any number of lists, each with any (>=0) number of tuples.
I'm both interested in solving this issue with some of Haskell's predefined functions (if possible), as well as with a somewhat similar approach as the one I was going for in the example above.
Thanks in advance!
This is simply the list monad, selecting an element from each list non-deterministically.
The function you're looking for is sequence :: Monad m => [m a] -> m [a] from Control.Monad
λ. let as = [(1,2),(3,4)]
λ. let bs = [(5,6)]
λ. let cs = [(7,8),(9,10)]
λ. let xss = [as, bs, cs]
λ. sequence xss
[[(1,2),(5,6),(7,8)]
,[(1,2),(5,6),(9,10)]
,[(3,4),(5,6),(7,8)]
,[(3,4),(5,6),(9,10)]
]
Here's a recursive solution
solution :: [[a]] -> [[a]]
solution (x: xs) = [y: ys | y <- x, ys <- solution xs]
solution [] = [[]]
The idea behind the solution is the following: prepend each element of the head of list to every list you get from recursively computing the result for the tail of the input list.
I am using the setxy function to set the area that my turtles will be placed in. I made a list of the x values and y values. But I don't want more than 1 turtle at the same point. I'm not sure how to stop this from happening. This is the code that I am using for this:
create-vcells 20
[ setxy one-of [0 0.6 1.2 1.8 2.4 3]
one-of [0 0.6 1.2 1.8 2.4] ]
Does anyone have any insight? Thanks!
I assume that vcells is a breed. I'll use regular turtle commands, but you'll be able to figure out how to adapt my examples to your code.
You can just use a double loop to look at each possible combination of x and y coordinates, putting the create- command inside the loops:
let xs [1 2 3 4]
let ys [10 15 20 25]
foreach xs [
let x ?
foreach ys [
let y ?
create-turtles 1 [setxy x y]
]
]
foreach loops through the items in a list (xs in the outer foreach, ys in the inner one). Inside a foreach block, ? refers to the current item from the list, and refers to each one in turn. I assigned the value of ? in the outer foreach block to a variable so that I could refer to its value from xs inside the inner foreach block, where ? would refer to one of the elements of ys instead. (Then I assigned the inner ? to a variable as well just for the sake of clarity.)
If instead of every combination of coordinates, you just want to pair the x-coordinates and y-coordinates in order, you can use foreach with multiple lists:
(foreach xs ys [
create-turtles 1 [setxy ?1 ?2]
])
Here ?1 refers to the current element from the first list (xs), and ?2 refers to the current element from the second list (ys). Note that in this case you have to wrap the entire expression in parentheses.
You can generate n unique pairs of coordinates (contained in your two lists) as follows:
to-report n-pairs [#n #lst01 #lst02]
let _n1 length #lst01
let _n2 length #lst02
let _nmax (_n1 * _n2) ;possible pairs
if (#n > _n1 * _n2) [error "#n is too big"]
let _idxs n-of #n n-values _nmax [?]
report map [(list
item int (? / _n2) #lst01
item (? mod _n2) #lst02)
] _idxs
end
I am new to Netlogo and still learning , what i want to do is call a list after an update is done and do another update to it until a condition is reached , if a have a list
let xy [[-2 6][-1 6][0 6][-1 6][-2 6][1 5][2 5][-3 9][-4 9][-5 9][-6 9][-3 9]]
let same true
I am trying to remove from the list the first sublist between two same elements [-2 6 ][-1 6][0 6][-1 6][-2 6] then i also want to remove the sublist between the other two same elements [-3 9][-4 9][-5 9][-6 9][-3 9] until there are no more elements that repeat in this case result should be [[1 5] [2 5]] and i control this list after removing the sublists with the condition:
if length xy = length remove-duplicates xy [ set same false ]
I have already done the removal code below and it removes the first sublist but i might have a lot of sublists , and i want to know how after one removal can i get again the updated list (in these case i should somehow take the final-list in the code) and control it again with these condition.
I was thinking to do a to-report procedure and a while loop , for example (maybe i am wrong with this)
to-report update-list [list]
while [same != false ]
[ ; do the removal stuff
set list-xy item POSITION (FIRST MODES xy) xy xy
let first-pos POSITION (FIRST MODES xy) xy
set list-temp remove-item first-pos xy
set sec-pos position list-xy list-temp + 1
set sublist-1 sublist xy 0 first-pos
set sublist-2 sublist xy sec-pos length xy
set final-list sentence sublist-1 sublist-2
set xy final-list
; the condition if i don't have any duplicates the size of two lists should have the same size , no duplicates
if length xy = length remove-duplicates xy
[ set same false ]
]
report update-list xy
I am not sure what to report at the end of the procedure and how to recall the list again, so i can remove all those sublists.
Any ideas are appreciated, thank you
This is easiest to solve using recursion:
to-report remove-fenced-sublists [xs]
if empty? xs
[ report [] ]
let pos position first xs butfirst xs
if not is-number? pos
[ report fput first xs remove-fenced-sublists butfirst xs ]
report remove-fenced-sublists sublist xs (pos + 2) length xs
end
Sample run:
observer> show remove-fenced-sublists [[-2 6][-1 6][0 6][-1 6][-2 6][1 5][2 5][-3 9][-4 9][-5 9][-6 9][-3 9]]
observer: [[1 5] [2 5]]
If I understand your goal, your core need can be captured by building up a new list item by item but trimming it whenever a duplicate appears. For a single new item this is:
to-report trim-or-grow [#list #item]
let _i position #item #list
report ifelse-value (_i != false) [sublist #list 0 _i] [lput #item #list]
end
You can then reduce with this reporter:
to test
let xy [[-2 6][-1 6][0 6][-1 6][-2 6][1 5][2 5][-3 9][-4 9][-5 9][-6 9][-3 9]]
print reduce trim-or-grow fput [] xy
end