cs50 mario less problem - my code is printing in a single line. I cant find whats wrong with it - cs50

#include <cs50.h>
#include <stdio.h>
int main(void)
{
int n;
do
{
n = get_int("Height: ");
}
while ((n < 1) || (n > 8));
for
(int i = 0; i < n; i++)
{for (int j = 0; j < n; j++)
if(i+j < n-1)
printf(" ");
else
printf("#");
}
printf("\n");
}

Make sure you use {} to enclose codes blocks for every for loop and if conditional. This printf("\n"); is outside both for blocks and thus prints exactly once. (The closing brace } before the final printf closes the code block of the i loop).

Your code is formatted poorly which makes it hard for yourself:
#include <cs50.h>
#include <stdio.h>
int main(void) {
int n;
do {
n = get_int("Height: ");
} while ((n < 1) || (n > 8));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
if(i + j < n - 1)
printf(" ");
else
printf("#");
}
printf("\n");
}
So you run you loops then print a single newline. It's not clear if you want:
newline after each " " and "#":
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
printf("%c\n", i + j < n - 1 ? ' ' : '#');
newline for each 'i':
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
printf("%c", i + j < n - 1 ? ' ' : '#');
printf("\n");
}

Related

How can I reverse print the characters of a string in each cell using AWK?

Beth 45 4.00 0 0 .072
Danny 33 3.75 ^0 0 .089
The above is the file I want to operate.
I want to write an AWK script that can reverse print the characters of a string in every cell.
Here is the code:
BEGIN { OFS = "\t\t" }
function reverse_print(str)
{
s = "";
N = length(str);
for (i = 1; i <= N; i++)
a[i] = substr(str, i, 1);
for (i = N; i >= 1; i--)
s = s a[i];
return s;
}
{
for (i = 1; i <= NF; i++)
$i = reverse_print($i) ;
print;
}
END {}
However, it does not work. The program somehow becomes dead.
I have found if I don't use the loop and handle each field one by one like the following,
BEGIN { OFS = "\t\t" }
function reverse_print(str)
{
s = "";
N = length(str);
for (i = 1; i <= N; i++)
a[i] = substr(str, i, 1);
for (i = N; i >= 1; i--)
s = s a[i];
return s;
}
{
$1 = reverse_print($1) ;
$2 = reverse_print($2) ;
$3 = reverse_print($3) ;
$4 = reverse_print($4) ;
$5 = reverse_print($5) ;
$6 = reverse_print($6) ;
print;
}
END {}
it can work well.
Here is my desired output:
hteB 54 00.4 0 0 270.
ynnaD 33 57.3 0^ 0 980.
I have thought hard but still cannot figure out where I did wrong using the loop.
Who can tell me why ?
You're using the same variable i inside and outside of the function. Use a different variable in either location or change the function definition to reverse_print(str, i) to make the i used within the function local to that function rather than the same global variable being used in the calling code.
You should also make s and N function local:
function reverse_print(str, i, s, N)
but in fact the code should be written as:
$ cat tst.awk
BEGIN { OFS = "\t\t" }
function reverse_print(fwd, rev, i, n)
{
n = length(fwd)
for (i = n; i >= 1; i--)
rev = rev substr(fwd, i, 1);
return rev
}
{
for (i = 1; i <= NF; i++)
$i = reverse_print($i)
print
}
$ awk -f tst.awk file
hteB 54 00.4 0 0 270.
ynnaD 33 57.3 0^ 0 980.
Could you please try following.(This program is tested on GNU awk only and as per Ed sir's comment too this is undefined behavior for POSIX awk)
awk '
BEGIN{
OFS="\t\t"
}
{
for(i=1;i<=NF;i++){
num=split($i,array,"")
for(j=num;j>0;j--){
val=(j<num?val:"") array[j]
}
printf "%s%s",val,(i<NF?OFS:ORS)}
val=""
}' Input_file
There is a rev command in Linux: rev - reverse lines characterwise.
You can reverse a string by calling rev with awk builtin function system like:
#reverse-fields.awk
{
for (i = 1; i <= NF; i = i + 1) {
# command line
cmd = "echo '" $i "' | rev"
# read output into revfield
cmd | getline revfield
# remove leading new line
a = gensub(/^[\n\r]+/, "", "1", revfield)
# print reversed field
printf("%s", a)
# print tab
if (i != NF) printf("\t")
# close command
close(cmd)
}
# print new line
print ""
}
$ awk -f reverse-fields.awk emp.data
0 00.4 hteB
0 57.3 naD
01 00.4 yhtaK
02 00.5 kraM
22 05.5 yraM
81 52.4 eisuS

squaring an int and showing the last digit - upgrade for a code

Could anyone help me to upgrade my code ?
I bet the function could be done in shorter and more elegant way, could you show me the proper direction or examples how to write that?
Thanks for the replies, here's the code ( written in Codeblocks 16.01):
#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int D,a,b,bb,liczba,dlugosc;
int main()
{
cout << "liczba testow: ";
cin >> D;
while(D<11 && D>0){
for (int j=0;j<D;j++){
cin >> a >> b;
if(a<0 | a>1000000000 | b<0 | b>1000000000){
break;
}
liczba =a;
for(int i=1;i<b;i++){
liczba = liczba*a;
}
char aa[10] = {0};
itoa(liczba,aa,10);
string bb = aa;
int dlugosc = bb.length();
cout << bb << endl;
cout << bb[dlugosc-1] << endl;
a = 0;
}
return 0;
}
return 0;
}

Read all the entries of a matrix using shell script

I have a matrix,
A(i,j), i=1,m and j=1,n
I can read it in C and FORTRAN, but I can't read it in shell script. I know this is a very simple question, but I am very new to shell script. I want to read all entries and do some calculation e.g. I have a matrix:
A= 1 0 1 1
2 1 0 2
1 0 0 3
1 2 3 0
Now I want to compare each 0 with its above, below, left and right values. Finally I want to do some computation (lets say sum) with these four values around each zero. In the above example the result will be- for five zeros
1st zero: 3
2nd zero: 4
3rd zero: 4
4th zero: 6
5th zero: 6
So in FORTRAN, I can do it by reading all the values as
do j=1,n
do i=1,m
if (A(i,j) .eq. 0) then
B(i,j)=A(i-1,j)+A(i+1,j)+A(i,j+1)+A(i,j-1)
enddo
enddo
But I want to do it in shell script. How to do?
Assuming that data are given in "test.dat" (with no "A = "), I tried it anyway...
#!/bin/bash
inpfile="test.dat"
L=100 # some large value
for (( i = 0; i < L; i++ )) {
for (( j = 0; j < L; j++ )) {
A[ L * i + j ]=0
}
}
i=1
while read buf; do
inp=( $buf ); n=${#inp[#]}
if (( L <= n+1 )); then echo "L is too small"; exit -1; fi
for (( j = 1; j <= n; j++ )) {
A[ L * i + j ]=${inp[j-1]}
}
(( i++ ))
done < $inpfile
nzeros=0
for (( i = 1; i <= n; i++ )) {
for (( j = 1; j <= n; j++ )) {
if (( ${A[ L * i + j ]} == 0 )); then
(( nzeros++ ))
B[ nzeros ]=$(( \
${A[ L * (i-1) + j ]} + \
${A[ L * (i+1) + j ]} + \
${A[ L * i + j+1 ]} + \
${A[ L * i + j-1 ]} ))
fi
}
}
for (( k = 1; k <= nzeros; k++ )) {
printf "%dst zero: %d\n" $k ${B[k]}
}
Conclusion: Very painful. Fortran is recommended...(as expected)

Using sed with an array to search for a string plus whitespace

I'm using sed to replace many lines in several files and I've run into a problem. I use an array to give sed many commands but need to include a couple spaces in the search to prevent sed form finding and deleting too many lines.
code:
( IFS='|'; sed -rie "/ ${points_r[*]};/d" io_points.dat4; )
The two spaces and ";" are to help avoid deleting lines I don't need to delete. Those lines were deleted, so I tried this as well:
( IFS='|'; sed -rie "/\s\{2,\}${points_r[*]};/d" io_points.dat4; )
My bash version is 3.2.25 and sed version is 4.1.5. How can I search for matches using this array, but include spaces (and ';') in the search? Any help would be greatly appreciated!
EDIT: sample input
2; 14; 1;I; 0; 1; 0; 66
3; 14; 1;I; 0; 1; 0; 141
4; 14; 1;I; 0; 1; 0; 23
5; 14; 1;I; 0; 1; 0; 26
7; 14; 1;I; 0; 1; 0; 0
points_r contains the numbers 3 4 and 5, I need to delete the lines which contain 3; 4; and 5; (first column) but not 2; or 7; (they contain a 4 in the second column)
Output would be:
2; 14; 1;I; 0; 1; 0; 66
7; 14; 1;I; 0; 1; 0; 0
Unless I misunderstood the requirements then simply do:
$ awk '/^[27];/' file
2; 14; 1;I; 0; 1; 0; 66
7; 14; 1;I; 0; 1; 0; 0
Or with sed:
$ sed '/^[27];/!d' file
2; 14; 1;I; 0; 1; 0; 66
7; 14; 1;I; 0; 1; 0; 0
In fact if this is the case you just want grep:
$ grep '^[27];' file
2; 14; 1;I; 0; 1; 0; 66
7; 14; 1;I; 0; 1; 0; 0
If you want the values to be in an array, try this script
$ echo "${points_r[#]}"
2 3 4
$ awk -F'[ ;]+' -v p="${points_r[*]}" 'BEGIN{split(p,a," ");for (i in a) b[a[i]]=1}!($2 in b)' file
2; 14; 1;I; 0; 1; 0; 66
7; 14; 1;I; 0; 1; 0; 0
Note that this will only work with singe word array elements.
Great script!
The problem is with using the pipe, and also with the array variable.
The 3.2 shell expands these a little differently.
assign the array to a different variable so that you don't have to do array expansion in the sed command (maybe not necessary, but makes things easier):
arr=$points_r[*]
Now do a shell substitution on the 'arr' variable to get the pipes in:
arr2="${arr// /|}"
Then use what you have, it's cool.
My shell prompt is ">>> ", and I unset IFS and OFS before this worked; for some reason they were pipes....
>>> x="${points_r[*]}"
>>> echo $x
3 4 5
>>> y="${x// /|}"
>>> echo $y
3|4|5
run the sed command with $y.
(The IFS won't be passed along to sed, I think. It receives 3 4 5 )
For the sed line you used, you need to enclose the regexp in () so it is one match group, (3 or 4 or 5)
sed -re "/ (${y});/d" io_points.dat4;
2; 14; 1;I; 0; 1; 0; 66
7; 14; 1;I; 0; 1; 0; 0
I haven't used the 'i' switch...

Implement an algorithm in bash

I have the following algorithm, and I want to implement it in bash.
void wepkey64(char *passphrase, unsigned char k64[4][5])
{
unsigned char pseed[4] = {0};
unsigned int randNumber, tmp;
int i, j;
for(i = 0; i < strlen(passphrase); i++)
{
pseed[i%4] ^= (unsigned char) passphrase[i];
}
randNumber = pseed[0] | (pseed[1] << 8) | (pseed[2] << 16) | (pseed[3] << 24);
for (i = 0; i < 4; i++)
{
for (j = 0; j < 5; j++)
{
randNumber = (randNumber * 0x343fd + 0x269ec3) & 0xffffffff;
tmp = (randNumber >> 16) & 0xff;
k64[i][j] = (unsigned char) tmp;
}
}
}
What's the equivalent of this function in bash?
Are you sure the /bin/sh on your system is actually the Bourne Shell? On many systems /bin/sh is actually the Boune-Again SHell (bash).. You can check with:
sh --version
If you have access to gawk, it has bitwise operators described here: http://www.gnu.org/software/gawk/manual/html_node/Bitwise-Functions.html
I think the original awk may lack these operators. But again, like sh and bash, awk usually is gawk on many systems.
Here's an awk solution
wepkey.awk
BEGIN{for(n=0;n<256;n++)ord[sprintf("%c",n)]=n}{print ord[$1]}
{
passphrase=$1
pseed[0]=0
pseed[1]=0
pseed[2]=0
pseed[3]=0
for (i=0; i<length(passphrase); i++)
{
pseed[i%4] = xor(pseed[i%4], ord[substr(passphrase,i+1,1)])
}
randNumber = or( or( or(pseed[0], lshift(pseed[1],8)), lshift(pseed[2],16)), lshift(pseed[3], 24))
for (i=0; i<4; i++)
{
for (j=0; j<5; j++)
{
randNumber=and(randNumber * 0x343fd + 0x269ec3, 0xffffffff)
tmp=and(rshift(randNumber, 16), 0xff)
printf "%02X", tmp
}
printf "\n"
}
}
to run it
echo passphrase | awk -f wepkey.awk

Resources