How to generate 3 natural number that sum to 60 using awk - linux

I am trying to write awk script that generate 3 natural numbers that sum to 60. I am trying with rand function but I`ve got problem with sum to 60

Here is one way:
awk -v n=60 'BEGIN{srand();a=int(rand()*n);b=int(rand()*(n-a));c=n-a-b;
print a,b,c}'
Idea is:
generate random number a :0=<a<60
generate random number b :0=<b<60-a
c=60-a-b
here, I set a variable n=60, to make it easy if you have other sum.
If we run this one-liner 10 times, we get output:
kent$ awk 'BEGIN{srand();for(i=1;i<=10;i++){a=int(rand()*60);b=int(rand()*(60-a));c=60-a-b;print a,b,c}}'
46 7 7
56 1 3
26 15 19
14 12 34
44 6 10
1 36 23
32 1 27
41 0 19
55 1 4
54 1 5

Related

What do "!" and "." mean in BASIC?

Trying to translate BASIC code written in the 1990's to Python. I keep coming across two symbols, ! (exclamation mark) and . (period). I can't find any documentation online on what they do.
I have the code running but some of the outputs are not as expected - I am wondering if these might be the issue as I previously thought that the period may just be a typo for a multiplication.
Examples:
|
v
QWLOST = (((TW-TDAO)/(TWRT-TDAOR))^1.25)*((VISR/VIS)^0.25).(PW+PE)*DT
TFAVE = (TTO+TBO)/2!
^
|
In case anyone else in the future needs to know this.
! - defines a single
. - Was just a typo for * (multiplication)
I tried a few things in bwBasic (in Linux, in case that's relevant!).
bwBASIC: list
10: for i = 1 to 20
20: print i, ., . - i
30: next i
40: print ".="; .
This gave me:
bwBASIC: run
1 20 19
2 20 18
3 20 17
4 20 16
5 20 15
6 20 14
7 20 13
8 20 12
9 20 11
10 20 10
11 20 9
12 20 8
13 20 7
14 20 6
15 20 5
16 20 4
17 20 3
18 20 2
19 20 1
20 20 0
.= 20
Which would suggest that . (in bwBasic in any case) is the max number in a for loop.

Efficient Reading of Input File

Currently for a task, I am working with input files which give Matrix related test cases (Matrix Multiplication) i.e., example of an input file ->
N M
1 3 5 ... 6 (M columns)
....
5 4 2 ... 1 (N rows)
I was using simple read() to access them till now, but this is not efficient for large files of size > 10^2.
So I wanted to know is there some way to use processes to do this in parallel.
Also I was thinking of using multiple IO readers based on line, so then each process could read different segments of the file but couldn't find any helpful resources.
Thank you.
PS: Current code is using this:
io:fread(IoDev, "", "~d")
Did you consider to use re module? I did not make a performance test, but it may be efficient. In the following example I do not use the first "M N" line. So I did not put it in the matrix.txt file.
matrix file:
1 2 3 4 5 6 7 8 9
11 12 13 14 15 16 17 18 19
21 22 23 24 25 26 27 28 29
31 32 33 34 35 36 37 38 39
I made the conversion in the shell
1> {ok,B} = file:read_file("matrix.txt"). % read the complete file and store it in a binary
{ok,<<"1 2 3 4 5 6 7 8 9\r\n11 12 13 14 15 16 17 18 19\r\n21 22 23 24 25 26 27 28 29\r\n31 32 33 34 35 36 37 38 39">>}
2> {ok,ML} = re:compile("[\r\n]+"). % to split the complete binary in a list a binary, one for each line
{ok,{re_pattern,0,0,0,
<<69,82,67,80,105,0,0,0,0,0,0,0,1,8,0,0,255,255,255,255,
255,255,...>>}}
3> {ok,MN} = re:compile("[ ]+"). % to split the line into binaries one for each integer
{ok,{re_pattern,0,0,0,
<<69,82,67,80,73,0,0,0,0,0,0,0,17,0,0,0,255,255,255,255,
255,255,...>>}}
4> % a function to split a line and convert each chunk into integer
4> F = fun(Line) -> Nums = re:split(Line,MN), [binary_to_integer(N) || N <- Nums] end.
#Fun<erl_eval.7.126501267>
5> Lines = re:split(B,ML). % split the file into lines
[<<"1 2 3 4 5 6 7 8 9">>,<<"11 12 13 14 15 16 17 18 19">>,
<<"21 22 23 24 25 26 27 28 29">>,
<<"31 32 33 34 35 36 37 38 39">>]
6> lists:map(F,Lines). % map the function to each lines
[[1,2,3,4,5,6,7,8,9],
[11,12,13,14,15,16,17,18,19],
[21,22,23,24,25,26,27,28,29],
[31,32,33,34,35,36,37,38,39]]
7>
if you want to check the matrix size, you can replace the last line with:
[[NbRows,NbCols]|Matrix] = lists:map(F,Lines),
case (length(Matrix) == NbRows) andalso
lists:foldl(fun(X,Acc) -> Acc andalso (length(X) == NbCols) end,true,Matrix) of
true -> {ok,Matrix};
_ -> {error_size,Matrix}
end.
is there some way to use processes to do this in parallel.
Of course.
Also I was thinking of using multiple IO readers based on line, so
then each process could read different segments of the file but
couldn't find any helpful resources.
You don't seek to positions in a file by line, rather you seek to byte positions. While a file may look like a bunch of lines, a file is actually just one long sequence of characters. Therefore, you will need to figure out what byte positions you want to seek to in the file.
Check out file:position, file:pread.

How can I use awk for modify a column based in the first column?

I have a data like this, and I need automatize a simple task. I need to make the second value of a row, become the same as the first cell in the next row in the sequence like this:
First Second
1 2
4 6
10 12
25 28
30 35
Become
First Second
1 4
4 10
10 25
25 30
30 35
$ awk 'NR==1; NR>2{print p[1], $1} {split($0,p)} END{print p[1], p[2]}' file
First Second
1 4
4 10
10 25
25 30
30 35
It should be noted your output is wrong, you cannot know the 35 because that row has not been read yet:
$ awk 'NR > 1 {print $1} {printf $1 "\t"}' file
1 4
4 10
10 25
25 30
30

Excel formula to get the count of certain value based on odd/even line

I have this data in Excel.
A B C
--------------------------------------
Line Number Value #1 Value #2
1 21 35
2 21 27
3 21 18
4 10 47
5 50 5
6 37 68
7 10 21
8 75 21
I tried to calculate the total "21" based on odd line number. In this situation, the answer should be 3. However, neither" IF(MOD(A1:A8,2)=1,COUNTIF(B1:C8,21)) " nor " {IF(MOD(A1:A8,2)=1,COUNTIF(B1:C8,21))} "worked and Google didn't yield anything helpful. Could anyone help me? Thanks!!
This works for odd lines:
=SUM(COUNTIF(A:B,21)-SUMPRODUCT((A:B=21)*(MOD(ROW(A:B),2)=0)))
there may be a better way of writing this formula.
Use this to count even lines:
=SUMPRODUCT((A:B=21)*(MOD(ROW(A:B),2)=0))

Find a pattern and modify the next line without modifying the other contents in the file. preferably linux based commands (sed, awk etc)

I have a file which looks like this:
# Hello, welcome to the world
# Trying to modify XXXXXX
# Some more random text
poly RANDOM LAYER{
20 25
18 2
1 5
1 2
5 6
}
poly RANDOM LAYER{
30 50
14 25
15 25
15 26
15 26
15 27
}
I would like to increment the values in the next line of poly RANDOM layer,say add 10 to the first number (20+10=30) and 20 to the next number (25+20=45). The rest of the contents should be the same:
This should be done for all the lines immediately after poly RANDOM LAYER
The output should look like:
# Hello, welcome to the world
# Trying to modify XXXXXX
# Some more random text
poly RANDOM LAYER{
*30 45*
18 2
1 5
1 2
5 6
}
poly RANDOM LAYER{
*40 60*
14 25
15 25
15 26
15 26
15 27
}
If the specific leading white space is always 4 chars:
$ awk 'f{$1=" "$1+10; $2+=20; f=0} /RANDOM/{f=1} 1' file
# Hello, welcome to the world
# Trying to modify XXXXXX
# Some more random text
poly RANDOM LAYER{
30 45
18 2
1 5
1 2
5 6
}
poly RANDOM LAYER{
40 70
14 25
15 25
15 26
15 26
15 27
}
otherwise use:
$ awk 'f{fmt=$0; gsub(/[^[:space:]]+/,"%s",fmt); $0=sprintf(fmt,$1+10,$2+20); f=0} /RANDOM/{f=1} 1' file
as that will just reproduce in your output WHATEVER leading, trailing, or inter-field white space you have in your input.
You say (sed, awk, etc). Is perl part of etc?
perl -pe 's/(\d+)/$1+10/ge if($lastLineMatch); $lastLineMatch = m/poly RANDOM/; ' < file
Or if you want to add different values to the two numbers:
perl -pe 's/(\d+)(\D+)(\d+)/($1+10).$2.($3+20)/ge if($lastLineMatch); $lastLineMatch = m/poly RANDOM/; ' < file

Resources