I'm trying to separate an array of integers to count how many repeated numbers are there.
For this input [10, 20, 20, 10, 10, 30, 50, 10, 20] I am receiving the following output:
#{10=>"\n\n\n\n",20=>[20,20],30=>[30],50=>"2"}
Question
I would like to know how can I generate the following output
#{10=>[10,10,10,10],20=>[20,20],30=>[30],50=>[50]}
The function I am using to generate the map output is:
%% Next: number
%% Acc: map
separate_socks(Next, Acc) ->
KeyExists = maps:is_key(Next, Acc),
case KeyExists of
true ->
CurrentKeyList = maps:get(Next, Acc),
maps:update(Next, [Next | CurrentKeyList], Acc);
false -> maps:put(Next, [Next], Acc)
end.
You can use the shell:strings/1 function to deal with the problem of numbers being displayed as characters. When shell:strings(true) is called, numbers will be printed as characters:
1> shell:strings(true).
true
2> [10,10,10].
"\n\n\n"
Calling shell:strings(false) will result in the numbers being printed as numbers instead:
3> shell:strings(false).
true
4> [10,10,10].
[10,10,10]
Your output is actually correct. The ascii value for \n is 10. There is no native string data type in erlang. A string is nothing by a list of values. erlang:is_list("abc") would return true.
Try [1010, 1020, 1020, 1010, 1010, 1030, 1050, 1010, 1020] as input. It should display all numbers.
You can also format the output with io:format():
1> M = #{10=>[10,10,10,10],20=>[20,20],30=>[30],50=>[50]}.
#{10 => "\n\n\n\n",20 => [20,20],30 => [30],50 => "2"}
2> io:format("~w~n", [M]).
#{10=>[10,10,10,10],20=>[20,20],30=>[30],50=>[50]}
ok
w
Writes data with the standard syntax. This is used to output Erlang
terms.
Related
Given the following code
defmodule Test do
def run do
p1 = {1, 2}
m1 = %{a: p1}
m2 = %{a: p1}
IO.puts :erts_debug.same(m1.a, m2.a)
m3 = %{b: p1}
IO.puts :erts_debug.same(m1.a, m3.b)
end
end
why does Test.run prints this
iex(1)> Test.run
true <--- expected
false <--- not true ?!
:ok
Why are m1.a and m3.b not the same in-memory tuple?
modern era update: seems like it was fixed in ≈v1.7.
This is true for Elixir only; in Erlang the tuple is shared:
1> Tuple = {1, 2},
1> Key1 = 1,
1> Key2 = 2,
1> Map1 = #{1 => Tuple, 2 => Tuple},
1> erts_debug:same(maps:get(Key1,Map1), maps:get(Key2,Map1)).
true
2> Key3 = 3,
2> Map2 = #{3 => Tuple},
2> erts_debug:same(maps:get(Key1,Map1), maps:get(Key3,Map2)).
true
For Elixir, this is probably because of internal transpiler to erlang duplicates maps or like. I’d say this could be a great bug report to Elixir core.
In your example :erts_debug.same(m1.a, m2.a) prints true only due to :erts_debug.same(m1, m2) #⇒ true, e.g. maps themselves share the same memory.
I have a file text "a.txt" :
1 2 3
4 5 6
7 8 9
Now i want store it in array 2d :
array ={ {1,2,3}{4,5,6}{7,8,9} }
I have try to :
array ={}
file = io.open("a.txt","r")
io.input(file)
i=0
for line in io.lines() do
array[i]=line
i=i+1
end
But it doesn't success.
Does anyone suggest me a way to do it?
You have some errors in your code. You first open the file a.txt and then set it for standard input. You don't need the open(). But i recommend to open the file and operate on it, using the lines() iterator on the file:
array = {}
file = io.open("a.txt","r")
i = 0
for line in file:lines() do
array[i]=line
i=i+1
end
Furthermore, with your method, you don't get the array you wished for ({ {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }) but instead an array containing strings as elements:
{ "1 2 3", "4 5 6", "7 8 9" }.
To get the latter, you have to parse the string you have read. An easy way to do this is to use string.match with captures:
array ={}
file = io.open("a.txt","r")
for line in file:lines() do
-- extract exactly three integers:
local t = { string.match(line, "(%d+) (%d+) (%d+)")) }
table.insert(array, t) -- append row
end
See https://www.lua.org/manual/5.3/manual.html#pdf-string.match. For a arbitrary number of integers (or other numbers) on every line, you can use a loop together with string.gmatch():
array ={}
file = io.open("a.txt","r")
for line in file:lines() do
local t = {}
for num in string.gmatch(line, "(%d+)") do
table.insert(t, num)
end
table.insert(array, t)
end
This is my code in question:
-module(test).
-export([seed_matrix2/0, take_row_and_column/4]).
seed_matrix2() ->
[0, 0, 1, 0,
4, 0, 0, 0,
0, 0, 0, 2,
0, 4, 0, 0].
take_row_and_column(R, C, AnsMatrix, SideLen) ->
RowVector = [ V || X <- lists:seq(0, SideLen-1), V <- lists:nth(R*SideLen+X, AnsMatrix) ],
ColVector = [ V || X <- lists:seq(0, SideLen-1), V <- lists:nth(X*SideLen+C, AnsMatrix) ],
{RowVector, ColVector}.
This is the error message I call the function test:take_row_and_column:
74> test:take_row_and_column(1, 2, test:seed_matrix2(), 4).
** exception error: no function clause matching
test:'-take_row_and_column/4-lc$^1/1-1-'(0) (/private/tmp/test.erl, line 12)
in function test:take_row_and_column/4 (/private/tmp/test.erl, line 12)
I usually get this when I am passing incorrect number of parameters or fail to satisfy the type guards. I do not understand why this code will trigger a no function clause matching
Here is the version banner of erl:
Erlang R16B03 (erts-5.10.4) [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Eshell V5.10.4 (abort with ^G)
The failing function in question is the compiler generated function for the list comprehension (note the "-lc$..." in the name). It looks like this is because your generator V <- lists:nth(..., Matrix) tries to pick a number V from a non-list, since lists:nth/2 will return the nth integer from the list. Writing the generator like V <- [lists:nth(...)] should work.
Here is the fix:
take_row_and_column(R, C, AnsMatrix, SideLen) ->
RowVector = [ lists:nth((R-1)*SideLen+X, AnsMatrix) || X <- lists:seq(1, SideLen-1) ],
ColVector = [ lists:nth((X-1)*SideLen+C, AnsMatrix) || X <- lists:seq(1, SideLen-1) ],
{RowVector, ColVector}.
There were two problems with the code in question:
1) lists:seq(0, ...) should be lists:seq(1, ...) instead. lists:nth() does not like value zero
2) erlang does not like the V<-... part. Need to move the whole lists:nth() call to the left of ||
I'm learing Erlang. Here is a simple task: convert integers like 1011, 111213, 12345678 to lists [10, 11], [11, 12, 13] and [12, 34, 56, 78] correspondingly.
Here is the function I wrote:
num_to_list(0) -> [];
num_to_list(Num) -> [Num rem 100 | [num_to_list((Num - Num rem 100) div 100)]].
But num_to_list(1234) gives me [34,[12,[]]]. Now I don't care that the list is reversed. I don't understand why it is not a plain list.
num_to_list returns list. You dont need use [] around it in num_to_list(Num). I mean
num_to_list(0) -> [];
num_to_list(Num) -> [Num rem 100 | num_to_list((Num - Num rem 100) div 100)].
I need to write a program, which returns a new list from a given list with following criteria.
If list member is negative or 0 it should and that value 3 times to new list. If member is positive it should add value 2 times for that list.
For example :
goal: dt([-3,2,0],R).
R = [-3,-3,-3,2,2,0,0,0].
I have written following code and it works fine for me, but it returns true as result instead of R = [some_values]
My code :
dt([],R):- write(R). % end print new list
dt([X|Tail],R):- X =< 0, addNegavite(Tail,X,R). % add 3 negatives or 0
dt([X|Tail],R):- X > 0, addPositive(Tail,X,R). % add 2 positives
addNegavite(Tail,X,R):- append([X,X,X],R,Z), dt(Tail, Z).
addPositive(Tail,X,R):- append([X,X],R,Z), dt(Tail, Z).
Maybe someone know how to make it print R = [] instead of true.
Your code prepares the value of R as it goes down the recursing chain top-to-bottom, treating the value passed in as the initial list. Calling dt/2 with an empty list produces the desired output:
:- dt([-3,2,0],[]).
Demo #1 - Note the reversed order
This is, however, an unusual way of doing things in Prolog: typically, R is your return value, produced in the other way around, when the base case services the "empty list" situation, and the rest of the rules grow the result from that empty list:
dt([],[]). % Base case: empty list produces an empty list
dt([X|Like],R):- X =< 0, addNegavite(Like,X,R).
dt([X|Like],R):- X > 0, addPositive(Like,X,R).
% The two remaining rules do the tail first, then append:
addNegavite(Like,X,R):- dt(Like, Z), append([X,X,X], Z, R).
addPositive(Like,X,R):- dt(Like, Z), append([X,X], Z, R).
Demo #2
Why do you call write inside your clauses?
Better don't have side-effects in your clauses:
dt([], []).
dt([N|NS], [N,N,N|MS]) :-
N =< 0,
dt(NS, MS).
dt([N|NS], [N,N|MS]) :-
N > 0,
dt(NS, MS).
That will work:
?- dt([-3,2,0], R).
R = [-3, -3, -3, 2, 2, 0, 0, 0] .
A further advantage of not invoking functions with side-effects in clauses is that the reverse works, too:
?- dt(R, [-3, -3, -3, 2, 2, 0, 0, 0]).
R = [-3, 2, 0] .
Of cause you can invoke write outside of your clauses:
?- dt([-3,2,0], R), write(R).
[-3,-3,-3,2,2,0,0,0]
R = [-3, -3, -3, 2, 2, 0, 0, 0] .