Note This SO should not have the raku tag. It is too obsolete/misleading. The technical problem discussed in the question body no longer applies. The disagreement in the comments about naming/tags no longer applies. I'm leaving it for historical interest only, under the old tag only.
I am learning Perl 6, and had trouble understanding the Perl 6 one-liner below
My Perl 6 is rakudo-star: stable 2014.04 (bottled)
This works fine. The array/list is sorted
[njia#mb-125:~] : perl6 -e 'say [2443,5,33, 90, -9, 2, 764].sort'
-9 2 5 33 90 764 2443
But this does not sort the array/list, if [].sort works why #s.sort does not?
[njia#mb-125:~] : perl6 -e 'my #s = [2443,5,33, 90, -9, 2, 764]; #s.sort.say'
2443 5 33 90 -9 2 764
Change from [] to ()
[njia#mb-125:~] : perl6 -e 'my #s = (2443,5,33,90,-9,2,764); #s.sort.say'
-9 2 5 33 90 764 2443
NOTE the described behavior in this question has changed in the release version of perl6. See response by G. Cito below.
For those who may be confused by this answer, the question is about Perl 6, and none of this applies to Perl 5.
The statement
my #s = [2443, 5, 33, 90, -9, 2, 764]
creates an itemised array and assigns it to #s[0], so #s has only a single element and sorting it is pointless.
However you can say
#s[0].sort.say
which has the effect you expected
I'm going to go out on a limb and refer to some of CPAN's Perl6 documentation where this could be viewed as a list vs. array thing - i.e. a sequence of values versus a sequence of itemized values (see doc.perl6.org).
Certainly perl6 is different enough that it warrants its own tag but it is still perl so it's not surprising that () creates a list and [] creates an anonymous array.
> say [2443, 5, 33, 90, -9, 2, 764].WHAT
(Array)
> say (2443, 5, 33, 90, -9, 2, 764).WHAT
(List)
Since this question was first asked and answered the behavior has changed:
> my #s = [2443, 5, 33, 90, -9, 2, 764]
> #s.sort.say
(-9 2 5 33 90 764 2443)
Note that the output when sorted is a List but otherwise #s is an Array:
> #s.sort.WHAT.say
(List)
> #s.WHAT.say
(Array)
Related
I am a beginner level in this program. I try to improve this loop according to this condition. The details are as follows:
When CUTI(k) = CUTI(k)-4 then,
1)If the result shows this CUTI(k) value greater than 0, then print this CUTI(k) value.
2)If the result shows CUTI(k) value less than 0, then print this CUTI(k) value is added 12 with showing a word "*" after the number in display, e.g. 10*, 9*
I am not sure this loop is correct and enough to add this condition. Look forward to seeing your recoomendation. :)
set k /1*20/;
parameter
CUTI(k)/1 6, 2 2, 3 8, 4 5, 5 1, 6 3, 7 7, 8 8, 9 6, 10 8,11 1, 12 2, 13 4, 14 7,
15 5, 16 2, 17 8, 18 9, 19 2, 20 10/;
loop(k,
if(CUTI(k)-4 > 0,
CUTI(k) = CUTI(k)-4;
else
CUTI(k) = (CUTI(k)-4)+12 ;
)
);
display CUTI;
Your logic looks correct. However, instead of the loop/if/else you could simplify this to one assignment:
CUTI(k) = CUTI(k)-4+12$(CUTI(k)<=4);
However, modifying the display statement by adding a * to some elements is not possible. If you need to distinguish the cases in such a statement, you might assign the values to two different parameters and display them individually.
First:
$ raku -e "for 1...6, 7...15 { .say }"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Now:
$ raku -e "for 1...3, 7...15 { .say }"
1
2
3
7
11
15
I would expect this case to print 1,2,3,7,8,... 15.
What's happening here?
I think you might want the raku Range operator .. (two dots) and not the raku Sequence operator ... (three dots).
Here's how you examples look with the Range operator instead:
> raku -e 'for 1..6, 7..15 { .say }'
1..6
7..15
Oh, that's not good ... looks like for is just iterating over the two things 1..6 and 7..15 and stringifying them.
We can use a Slip | to fix that:
> raku -e 'for |(1..6), |(7..15) { .say }'
1
2
... (all the numbers)
14
15
And then:
raku -e 'for |(1..3), |(7..15) { .say }'
1
2
3
7
8
9
10
11
12
13
14
15
With the Sequence operator, you have made something like:
>raku -e 'for 3,7...15 { .say }'
3
7
11
15
That is raku for "make a sequence that starts with 3, then 7, then all the values until you get to the last at 15" ... and since the gap from 3 to 7 is 4, raku will count up in steps of 4. Then you began it with 1..3. ;-)
~p6steve
It's because it is two deductive sequences.
1...3
Is obviously a sequence where you add 1 to each successive value.
1, 2, 3
And since 7 is 4 more than 3, this is a sequence where you add 4 to each successive value.
3, 7 ... 15
3, 7, 11, 15
To get what you want, you could use a flattened Range.
1...3, |(7..15)
Or even a flattened Sequence.
1...3, |(7...15)
TL;DR This answer focuses on addressing what you originally asked (which was about "sequences") and precisely what the code you wrote is doing, rather than providing a solution (using ranges instead).
This is a work in progress dealing with something that seems both poorly documented and hard to fathom (which may explain part though not all of the doc situation). Please bear with me! (And I may just end up deleting this answer.)
1 ... 3, 7 ... 15 ≡ 1 ... (3, 7) ... 15
In the absence of parentheses, operators within an expression are applied according to rules of "precedence" and "associativity".
Infix , has a higher precedence than infix ....¹ The above two lines of code thus produce the same result (12371115):
for 1 ... 3, 7 ... 15 { .say } # Operator evaluation by precedence
for 1 ... (3, 7) ... 15 { .say } # Operator evaluation by parentheses
That said, while the result is what, given a glance at the code, I would expect based on my own "magical" DWIM ("Do What I Mean") thinking, I must say I don't yet know what the precise Raku(do)'s rule(s) are that lead to it DWIMing.
The doc for infix ... says:
If the endpoint is not *, it's smartmatched against each generated element and the sequence is terminated when the smartmatch succeeded.
But that seems overly simple. What if the endpoint of one sequence is another sequence? (As, at least taking a naive view, appears to be the case in your code.)
Also, as #MustafaAydin has noted:
how does your post explain the irregular last step size (of 2) instead of 3? I mean 4, 7 ... 15 alone produces (4, 7, 10, 13). But 1... 4, 7...15 now produces 7, 10, 13, 15 in the tail. Why is 15 included? Maybe i'm missing something idk
I'm at least as confused as Mustafa.
Indeed, I'm confused about several things. How come Raku(do) flattens the two sequences? [D'oh. Because the infix comma is higher precedence than the infix ....] Why doesn't it repeat the 3 in the final combined list? [Perhaps because multiple infix ...s are smart about what to do when there's an expression that's the endpoint of one sequence and the start of another?]
I'm going to go read the old design docs and/or spelunk roast and/or the Rakudo compiler code to see if I can see what's supposedly/actually going on. But not tonight.
Footnotes
¹ There's a table of operators in the current official operator doc. Supposedly this table:
summarizes the precedence levels offered by Raku, listing them in order from high to low precedence.
Unfortunately, at the time of writing this, the central operator table in the Operators page is profoundly wrong #4071.
Until that's fixed, here are "official" and "unofficial" options for determining the precedence of operators:
"official" Use in page search to search the official doc operator page for the operator of interest. Skip to the match in the entries on the left hand side of that same page. As you'll see, infix ,' is one level higher precedence than infix ...`:
Comma operator precedence
infix ,
infix :
List infix precedence
infix Z
infix X
infix ...
"unofficial" Look at the corresponding page of a staging site for an improved doc site. (I don't know how up to date it is, but the central table appears to list operators by precedence order as it claims.)
I am trying to break down a given number into 10 equal parts and then compare a row of numbers and see in which of the 10 parts they fall under.
ref_number, number_to_check
70, 34
70, 44
70, 14
70, 24
In the above data set, I would like to break 70 into 10 equal parts (in this case it would be 7,14,21, and so on till 70). Next I would like to see in which "part" does the value in column "number_to_check" fall into.
Output expected:
ref_number, number_to_check, part
70, 34, 5
70, 44, 7
70, 14, 2
70, 24, 4
You want arithmetic. If I understand correctly:
select ceiling(number_to_check * 10.0 / ref_number)
Here is a db<>fiddle (the fiddle happens to use Postgres).
I'm trying to read an input file with fortran but I get the following error at runtime:
At line 118 of file prog.f90 (unit = 53, file = 'data.dat')
Fortran runtime error: Bad repeat count in item 1 of list input
The data file is the following
3, 5, 3 %comment
%%%%%%%%%%%%%%
1d0, 0d0, 0d0 % comment
0d0, 0d0, 1d0
%%%%%%%%%%%%%%
1, 1, identity, 1, 1 %comment
1, 2, sigmax, 2, 2
2, 3, sigmax, 2, 2
1, 3, sigmaz, 1, 3
3, 3, identity, 1, 1
%%%%%%%%%%%%%%
0, 0 %comment
and the interesting part of prog.f90 is
COMPLEX(KIND(1D0)), DIMENSION(:), ALLOCATABLE:: H1, H2
INTEGER :: i,A,B,C
CHARACTER(50) :: GHOST
OPEN(UNIT=53,file='data.dat',status='old')
READ(53,*) A,B,C
READ(53,*) GHOST
ALLOCATE (H1(A),H2(A))
READ(53,*) (H1(i), i=1,A)
READ(53,*) (H2(i), i=1,A)
where the 118th line is READ(53,*) (H1(i), i=1,A). I tryed also with an explicit do loop but with the same result.
I haven't tested this, but I'd expect
READ(53,*) (H1(i), i=1,A)
to try to read 3 complex numbers. It gets fed the line
1d0, 0d0, 0d0 % comment
from which it gets 1½ complex numbers and then barfs on the % sign, misinterpreting it as a syntactically invalid repeat count.
I'd suggest providing 3 complex numbers in the file when that read statement is executed.
The numbers are dimensioned complex, while in fortran complex numbers should be in the file with parenthesis as:
( realpart , imaginarypart ) ( realpart , imaginarypart )
I really don't know what the standards say regarding the input form you have presented, but after some testing gfortran throws that Bad repeat count error regardless of the % comment. It throws that error even with four or more comma separated reals on the line.
Now ifort on the other hand reads the line just the way you have it -- but watch out -- it reads each of the comma separated values as the real part of your complex variable, setting the imaginary part to zero. ( that is it only uses the first two values on each line and discards the third )
You will really need to study the code to make sure you understand what was intended to sort out how to fix this. If the later (ifort) behavior is the intention one simple fix would be to declare a couple of reals. Read into the reals, then assign those to your complex variables.
I can find sed solutions to delete all lines in a text file starting with a '1' as well as solutions to delete every other line of all the lines in the text file but I want to combine the two.. of all the lines starting with '1' delete every other one of them and keep the other lines that do not start with a 1.
So if I have a text file:
1, 1
1, 2
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
1, 9
4, 10
I want the output to be:
1, 1
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
4, 10
You could do this in awk:
awk -F, '!($1 == 1 && n++ % 2)' file
-F, means use comma as the field separator, so the two numbers on each line will be the variables $1 and $2.
awk will print the line if the last thing it evaluates is true. The ! negates the contents of the parentheses, so in order to print, the contents must be false.
If the first field isn't 1, short-circuiting takes place, as (false && anything) will always be false. This means that the second half after the && will not be evaluated.
If $1 == 1, then the second half is evaluated. As n is being used for the first time in a numeric context, it will assume the value 0. The modulo operation n % 2 will return 0 (false) for even numbers and 1 (true) for odd numbers. Using the increment n++ means that the result will alternate between true and false.
You may prefer the reverse logic, which would be:
awk -F, '$1 != 1 || ++n % 2' file
The || is also short-circuiting, so if the first value isn't 1 then the line gets printed. Otherwise, the second half is evaluated. This time, the increment goes before the n so that the first value of n is 1, making the expression evaluate to true.
Either way, the output is:
1, 1
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
4, 10
This might work for you (GNU sed):
sed '/^1/{x;/./{z;x;d};x;h}' file
Use the hold space to toggle the deletion of lines beginning with 1.
An alternative:
sed '/^1/{:a;n;//d;ba}' file
Here you go:
awk '$1=="1," && !(f=f?0:1) {next} 1' file
1, 1
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
4, 10
$1=="1," Test if first field is 1
f=f?0:1 Flop the f between 0 and 1 for every time $1=="1," is true
!(...) True if f is 0
Here's an awk-based solution without requiring any modulo math whatsoever :
[ngm]awk 'FS~NF||_*=--_' FS='^1'
|
1, 1
2, 3
3, 4
4, 5
2, 6
1, 7
3, 8
4, 10
This leverages the interesting property that x *= --x generates an alternating sequence of 1s and 0s that never converges and never diverges.