Pattern matching and list comprehension with binary - binary

Using list comprehension, elixir allow do pattern matching like that:
iex()> for {a,2,c} = ch <- [{1,2,3},{4,5,6},3,4,5], do: c
[3]
But when I'm trying to do something like that with binary, I fail:
iex()> for << b1::size(2), b2::size(3), b3::size(3) >> = <<ch>> <- 'hello', do: b1
[]
Nevertheless, it matches well when standalone:
<< b1::size(2), b2::size(3), b3::size(3) >> = <<100>>
"d"
iex(282)> b2
4
iex(283)> b1
1
iex(284)> b3
4
It also works well when I pass mattern matching clause as secornd parameter to for:
iex(286)> for ch <- 'hello', << b1::size(2), b2::size(3), b3::size(3) >> = <<ch>>, do: b1
[1, 1, 1, 1, 1]
I'm interested if it possible to do something like first example with binary.

This is what fails:
<<ch>> <- 'hello'
In your very first example you do var <- list and later you try <<var>> <- list which is not the same by all means.
'hello' is the list of integers in the first place. Check this:
[104,101,108,108,111]
#⇒ 'hello'
Kernel.SpecialForms.for/1 is iterating through the list, one by one. One cannot match binary to an integer as is:
<<_::size(2), _::size(3), _::size(3)>> = 101
#⇒ ** (MatchError) no match of right hand side value: 101
And also:
<<ch>> = 101
#⇒ ** (MatchError) no match of right hand side value: 101
The latter code example from your question works because you match to an integer and then explicitly tell to Elixir/Erlang it’s to be treated as binary by wrapping it with << >>:
<<b1::size(2), _::size(3), _::size(3)>> = <<101>>
#⇒ "e"

Related

Substring question on mips assembly language

Please help as soon as possible...
Write a MIPS assembly language program that prompts the user to input two strings (each should be no longer than 50 characters including the null terminator). Your program should determine whether the second string is a substring of the first. If it is, then your program should print out the first index in which the second string appears in the first. For example, if the first string is “Hello World” and the second string is “lo”, then the program should print out 3, i.e. the starting index of “lo” in “Hello World.” If the second string is not contained in the first string, then your program should print out -1.
To be able to understand what you have to implement at assembly level, the first thing you should do, is understanding the high-level algorithm. Why?
It's easier for you to see all the cases and edge-cases in time!
To look back at what have I been trying to do again? in the middle of programming the Assembly version.
To quickly see which variables you (certainly) need.
I wrote following program (forgive me, python has been a while for me):
def is_in_string_1(string, substring):
"""
aaba: a, b, ab, ba, aba (last one will fail)
"""
length = len(string)
sublength = len(substring)
if (sublength == 0):
return True
j = 0
for i in range(0, length):
if string[i] != substring[j]:
j = 0
else:
j += 1
if j == sublength:
return True
return False
def is_in_string_2(string, substring):
"""
aaba: a, b, ab, ba, aba
"""
length = len(string)
sublength = len(substring)
for i in range(0, length + 1 - sublength): # string: aabc; substring: c; length: 4; sublength: 1; indexes: 0,1,2,3;
is_substring = True
for j in range(0, sublength): # for the sake of the algorithm, no slicing here
if string[i+j] != substring[j]:
is_substring = False
break
if is_substring:
return True
return False
stringTuples = [
("aaa", "aa"),
("aaa", "aaa"),
("aaa", "aab"),
("abc", "bc"),
("abc", "a"),
("abc", "abc"),
("aaa", ""),
("aaa", "b")
]
for stringTuple in stringTuples:
print(
stringTuple[0],
stringTuple[1],
':',
is_in_string_1(stringTuple[0], stringTuple[1]),
is_in_string_2(stringTuple[0], stringTuple[1]),
sep='\t'
)
I first thought I could optimize the standard solution (is_in_string_2), leaving out the second for-loop (is_in_string_1), but after some thinking I already found out it would fail (the edge-case wasn't even in any of my test-data!) - so I left it as an example for how important it is that you use a correct algorithm.
The program produces the following output:
aaa aa : True True
aaa aaa : True True
aaa aab : False False
abc bc : True True
abc a : True True
abc abc : True True
aaa : True True
aaa b : False False
aaba aba : False True
Notice how all output was correct, except for the last line, where the first algorithm is wrong.
Before you continue:
You have to make your own len() function in MIPS; note that all string are (if I remember correctly) null terminated, so you'll have to count all non-null characters of a string, or in other words, count how many characters precede the null-terminator.
You should use j, $ra and jr calls to go to a "function" or subroutines. (Search)
While in one, you can call other functions using the stack. (Search)

How does the 'k' modifier in FINDC() work in SAS?

I'm reading through the book, "SAS Functions by Example - Second Edition" and having trouble trying to understand a certain function due to the example and output they get.
Function: FINDC
Purpose: To locate a character that appears or does not appear within a string. With optional arguments, you can define the starting point for the search, set the direction of the search, ignore case or trailing blanks, or look for characters except the ones listed.
Syntax: FINDC(character-value, find-characters <,'modifiers'> <,start>)
Two of the modifiers are i and k:
i ignore case
k count only characters that are not in the list of find-characters
So now one of the examples has this:
Note: STRING1 = "Apples and Books"
FINDC(STRING1,"aple",'ki')
For the Output, they said it returns 1 because the position of "A" in Apple. However this is what confuses me, because I thought the k modifier says to find characters that are not in the find-characters list. So why is it searching for a when the letter "A", case-ignored, is in the find-characters list. To me, I feel like this example should output 6 for the "s" in Apples.
Is anyone able to help explain the k modifier to me any better, and why the output for this answer is 1 instead of 6?
Edit 1
Reading the SAS documentation online, I found this example which seems to contradict the book I'm reading:
Example 3: Searching for Characters and Using the K Modifier
This example searches a character string and returns the characters that do
not appear in the character list.
data _null_;
string = 'Hi, ho!';
charlist = 'hi';
j = 0;
do until (j = 0);
j = findc(string, charlist, "k", j+1);
if j = 0 then put +3 "That's all";
else do;
c = substr(string, j, 1);
put +3 j= c=;
end;
end;
run;
SAS writes the following output to the log:
j=1 c=H
j=3 c=,
j=4 c=
j=6 c=o
j=7 c=!
That's all
So, is the book wrong?
The book is wrong.
511 data _null_;
512 STRING1 = "Apples and Books" ;
513 x=FINDC(STRING1,"aple",'ki');
514 put x=;
515 if x then do;
516 ch=char(string1,x);
517 put ch=;
518 end;
519 run;
x=6
ch=s

csv empty strings handling and values appending

With a csv of ~50 rows (stars) and ~30 columns (name, magnitudes and distance), that has some empty string values (''), I am trying to do two things in which all the help so far hasn't been useful. (1) I need to parse empty strings as 0.0, so I can (2) append each row in a list of lists (what I called s).
In other words:
- s is a list of stars (each one has all its parameters)
- d is a particular parameter for all the stars (distance), which I obtain correctly.
Big issue is with s. My try:
with open('stars.csv', 'r') as mycsv:
csv_stars = csv.reader(mycsv)
next(csv_stars) #skip header
stars = list(csv_stars)
s = [] # star
d = [] # distances
for row in stars:
row[row==''] = '0'
s.append(float(row)) #stars
d.append(arcsec*AU*float(row[30]))
I can't think of a better syntax, and so I get the error
s.append(float(row)) # stars
TypeError: float() argument must be a string or a number
From s I would obtain later the magnitudes for all the stars, separately. But first things first...
#cwasdwa Please look at below code. it will give you an idea. I am sure there might be better way. This solution is based on what I have understood from your code.
with open('stars.csv', 'r') as mycsv:
csv_stars = csv.reader(mycsv)
next(csv_stars) #skip header
stars = list(csv_stars)
s = [] # star
d = [] # distances
for row in stars:
newRow = [] #create new row array to convert all '' to 0.0
for x in row:
if x =='':
newRow.append(0.0)
else:
newRow.append(x)
s.append(newRow) #stars
if row[30] == '':
value = 0.0
else:
value = row[30]
d.append(arcsec*AU*float(value))

Egg dropping in worst case

I have been trying to write an algorithm to compute the maximum number or trials required in worst case, in the egg dropping problem. Here is my python code
def eggDrop(n,k):
eggFloor=[ [0 for i in range(k+1) ] ]* (n+1)
for i in range(1, n+1):
eggFloor[i][1] = 1
eggFloor[i][0] = 0
for j in range(1, k+1):
eggFloor[1][j] = j
for i in range (2, n+1):
for j in range (2, k+1):
eggFloor[i][j] = 'infinity'
for x in range (1, j + 1):
res = 1 + max(eggFloor[i-1][x-1], eggFloor[i][j-x])
if res < eggFloor[i][j]:
eggFloor[i][j] = res
return eggFloor[n][k]print eggDrop(2, 100)
```
The code is outputting a value of 7 for 2eggs and 100floors, but the answer should be 14, i don't know what mistake i have made in the code. What is the problem?
The problem is in this line:
eggFloor=[ [0 for i in range(k+1) ] ]* (n+1)
You want this to create a list containing (n+1) lists of (k+1) zeroes. What the * (n+1) does is slightly different - it creates a list containing (n+1) copies of the same list.
This is an important distinction - because when you start modifying entries in the list - say,
eggFloor[i][1] = 1
this actually changes element [1] of all of the lists, not just the ith one.
To instead create separate lists that can be modified independently, you want something like:
eggFloor=[ [0 for i in range(k+1) ] for j in range(n+1) ]
With this modification, the program returns 14 as expected.
(To debug this, it might have been a good idea to write out a function to pring out the eggFloor array, and display it at various points in your program, so you can compare it with what you were expecting. It would soon become pretty clear what was going on!)

Display struct fields without the mess

I have a struct in Octave that contains some big arrays.
I'd like to know the names of the fields in this struct without having to look at all these big arrays.
For instance, if I have:
x.a=1;
x.b=rand(3);
x.c=1;
The obvious way to take a gander at the structure is as follows:
octave:12> x
x =
scalar structure containing the fields:
a = 1
b =
0.7195967 0.9026158 0.8946427
0.4647287 0.9561791 0.5932929
0.3013618 0.2243270 0.5308220
c = 1
In Matlab, this would appear as the more succinct:
>> x
x =
a: 1
b: [3x3 double]
c: 1
How can I see the fields/field names without seeing all these big arrays?
Is there a way to display a succinct overview (like Matlab's) inside Octave?
Thanks!
You might want to take a look at Basic Usage & Examples. There's several functions mentioned that sound like they'll control the displaying in the terminal.
struct_levels_to_print
print_struct_array_contents
These two functions sound like they're do what you want. I tried both and couldn't get the 2nd one to work. The 1st function changed the terminal output like so:
octave:1> x.a=1;
octave:2> x.b=rand(3);
octave:3> x.c=1;
octave:4> struct_levels_to_print
ans = 2
octave:5> x
x =
{
a = 1
b =
0.153420 0.587895 0.290646
0.050167 0.381663 0.330054
0.026161 0.036876 0.818034
c = 1
}
octave:6> struct_levels_to_print(0)
octave:7> x
x =
{
1x1 struct array containing the fields:
a: 1x1 scalar
b: 3x3 matrix
c: 1x1 scalar
}
I'm running a older version of Octave.
octave:8> version
ans = 3.2.4
If I get a chance I'll check that other function, print_struct_array_contents, to see if it does what you want. Octave 3.6.2 looks to be the latest version as of 11/2012.
Use fieldnames ()
octave:33> x.a = 1;
octave:34> x.b = rand(3);
octave:35> x.c = 1;
octave:36> fieldnames (x)
ans =
{
[1,1] = a
[2,1] = b
[3,1] = c
}
Or you you want it to be recursive, add the following to your .octaverc file (you may want to adjust it to your preferences)
function displayfields (x, indent = "")
if (isempty (indent))
printf ("%s: ", inputname (1))
endif
if (isstruct (x))
printf ("structure containing the fields:\n");
indent = [indent " "];
nn = fieldnames (x);
for ii = 1:numel(nn)
if (isstruct (x.(nn{ii})))
printf ("%s %s: ", indent, nn{ii});
displayfields (x.(nn{ii}), indent)
else
printf ("%s %s\n", indent, nn{ii})
endif
endfor
else
display ("not a structure");
endif
endfunction
You can then use it in the following way:
octave> x.a=1;
octave> x.b=rand(3);
octave> x.c.stuff = {2, 3, 45};
octave> x.c.stuff2 = {"some", "other"};
octave> x.d=1;
octave> displayfields (x)
x: structure containing the fields:
a
b
c: structure containing the fields:
stuff
stuff2
d
in Octave, version 4.0.0 configured for "x86_64-pc-linux-gnu".(Ubuntu 16.04)
I did this on the command line:
print_struct_array_contents(true)
sampleFactorList % example, my nested structure array
Output: (shortened):
sampleFactorList =
scalar structure containing the fields:
sampleFactorList =
1x6 struct array containing the fields:
var =
{
[1,1] = 1
[1,2] =
2 1 3
}
card =
{
[1,1] = 3
[1,2] =
3 3 3
}
To disable/get back to the old behaviour
print_struct_array_contents(false)
sampleFactorList
sampleFactorList =
scalar structure containing the fields:
sampleFactorList =
1x6 struct array containing the fields:
var
card
val
I've put this print_struct_array_contents(true) also into the .octaverc file.