Why does GCC for Risc-V generate nop instructions after call - gcc

GCC for Risc-V produces nop instructions after call instructions by default:
$ cat test.c
void g();
void f() {
g();
}
$ riscv64-unknown-elf-gcc -S test.c -o -
[...]
f:
addi sp,sp,-16
sd ra,8(sp)
sd s0,0(sp)
addi s0,sp,16
call g
nop #### <-----------here
ld ra,8(sp)
ld s0,0(sp)
addi sp,sp,16
jr ra
.size f, .-f
.ident "GCC: (GNU) 8.3.0"
I'd expect that when targeting an architecture that has branch delay slot, but my understanding is that Risc-V is not such an architecture. Actually, the nop disappears when compiling with -O1 or higher.
Is it just a "bug" in GCC that emits nop as a leftover from architectures that have delay slots, or is there an actual reason for this nop instruction?

Not a complete answer, but at least an attempt at diving into the reason why the nop appears. I strongly believe it's a bug/leftover from architectures that have delay slots (as it gets added in the very first RTL pass - expand).
Onto the investigation, GCC has 2 types of passes, Tree and RTL. To see them in action, prep 2 folders as there will be many files, noopt and opt and use the -fdump-tree-all-raw -fdump-rtl-all to see the intermediate results. The last stage of the Tree pass gives (noopt case):
$ cat noopt/test.c.232t.optimized
;; Function f (f, funcdef_no=0, decl_uid=1549, cgraph_uid=0, symbol_order=0)
f ()
{
<bb 2> :
gimple_call <g, NULL>
gimple_return <NULL NULL>
}
The opt case (-O1) differs negligibly:
$ diff -u noopt/test.c.232t.optimized opt/test.c.232t.optimized
--- noopt/test.c.232t.optimized 2019-09-03 14:48:02.874071927 +0200
+++ opt/test.c.232t.optimized 2019-09-03 14:48:29.550278667 +0200
## -3,7 +3,7 ##
f ()
{
- <bb 2> :
+ <bb 2> [local count: 1073741825]:
gimple_call <g, NULL>
gimple_return <NULL NULL>
The first stage of the RTL passes (expand) is the one that differs:
$ cat noopt/test.c.234r.expand
;; Function f (f, funcdef_no=0, decl_uid=1549, cgraph_uid=0, symbol_order=0)
;; Generating RTL for gimple basic block 2
try_optimize_cfg iteration 1
Merging block 3 into block 2...
Merged blocks 2 and 3.
Merged 2 and 3 without moving.
Merging block 4 into block 2...
Merged blocks 2 and 4.
Merged 2 and 4 without moving.
try_optimize_cfg iteration 2
;;
;; Full RTL generated for this function:
;;
(note 1 0 3 NOTE_INSN_DELETED)
(note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
(call_insn 5 2 8 2 (parallel [
(call (mem:SI (symbol_ref:DI ("g") [flags 0x41] <function_decl 0x7fbc2827a400 g>) [0 g S4 A32])
(const_int 0 [0]))
(clobber (reg:SI 1 ra))
]) "../test.c":3 -1
(nil)
(nil))
(insn 8 5 0 2 (const_int 0 [0]) "../test.c":4 -1
(nil))
The difference with -O1 is just removing that const_int 0 [0], which will ultimately lead to the nop:
$ diff -u noopt/test.c.234r.expand opt/test.c.234r.expand
--- noopt/test.c.234r.expand 2019-09-03 14:48:02.874071927 +0200
+++ opt/test.c.234r.expand 2019-09-03 14:48:29.550278667 +0200
## -25,12 +25,10 ##
(note 1 0 3 NOTE_INSN_DELETED)
(note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
-(call_insn 5 2 8 2 (parallel [
- (call (mem:SI (symbol_ref:DI ("g") [flags 0x41] <function_decl 0x7fbc2827a400 g>) [0 g S4 A32])
+(call_insn 5 2 0 2 (parallel [
+ (call (mem:SI (symbol_ref:DI ("g") [flags 0x41] <function_decl 0x7f0bdec1f400 g>) [0 g S4 A32])
(const_int 0 [0]))
(clobber (reg:SI 1 ra))
]) "../test.c":3 -1
(nil)
(nil))
-(insn 8 5 0 2 (const_int 0 [0]) "../test.c":4 -1
- (nil))

GCC will probably do this on any architecture. I think the nop instruction is related to the void result, it's where a non-void function would set up the return value. Try compiling this:
int g();
int f() {
g();
return 1;
}
For a void function, there is nothing to do to generate the result, hence the nop.

Related

Verilog nested for loop in testbench no iterating correctly

Good evening,
I designed a structural design of the MC14585B magnitude comparator: https://www.onsemi.com/pub/Collateral/MC14585B-D.PDF
I wanted to simulate all 2^8 possibilities and so I wrote a testbench to just that. I am using modelsim student edition:
source:
module MC14585(
input [3:0] A, B,
input A_less_B_in, A_greater_B_in, A_equal_B_in,
output A_less_B_out, A_greater_B_out, A_equal_B_out);
wire [3:0] exor, not_A, not_B, nand1, or1;
wire not_A_less_B_in, not_A_equal_B_in, nand2, nor1;
not n1(not_A_less_B_in, A_less_B_in);
not n2(not_A_equal_B_in, A_equal_B_in);
xor x1(exor[0], A[0], B[0]);
xor x2(exor[1], A[1], B[1]);
xor x3(exor[2], A[2], B[2]);
xor x4(exor[3], A[3], B[3]);
not n3(not_A[0], A[0]);
not n4(not_A[1], A[1]);
not n5(not_A[2], A[2]);
not n6(not_A[3], A[3]);
not n7(not_B[0], B[0]);
not n8(not_B[1], B[1]);
not n9(not_B[2], B[2]);
not n10(not_B[3], B[3]);
nand na1(nand1[0], not_A[0], B[0]);
nand na2(nand1[1], not_A[1], B[1]);
nand na3(nand1[2], not_A[2], B[2]);
nand na4(nand1[3], not_A[3], B[3]);
or o1(or1[0], exor[3], exor[2], exor[1], exor[0], not_A_less_B_in);
or o2(or1[1], exor[3], exor[2], exor[1], nand1[0]);
or o3(or1[2], exor[3], exor[2], nand1[1]);
or o4(or1[3], exor[3], nand1[2]);
nand na5(nand2, or1[0], or1[1], or1[2], or1[3], nand1[3]);
nand na6(A_less_B_out, or1[0], or1[1], or1[2], or1[3], nand1[3]);
nor not_or1(nor1, exor[0], exor[1], exor[2], exor[3], not_A_equal_B_in);
nor not_or2(A_greater_B_out, nand2, nor1);
endmodule
testbench:
`timescale 1ns / 1ps
module Assignment1_tb();
reg[3:0] A, B;
wire A_less_B, A_greater_B, A_equal_B;
MC14585 MC14585_DUT(
.A(A),
.B(B),
.A_less_B_in(1'b0),
.A_greater_B_in(1'b0),
.A_equal_B_in(1'b1),
.A_less_B_out(A_less_B),
.A_greater_B_out(A_greater_B),
.A_equal_B_out(A_equal_B));
initial begin
for (A = 0; A < 16; A=A+1) begin
for (B = 0; B < 16; B=B+1) begin
if (A_less_B && (A < B))
$display ("%d is less than %d", A, B);
else if (A_greater_B && (A > B))
$display ("%d is greater than %d", A, B);
else if (A_equal_B && (A == B))
$display ("%d is equal to %d", A, B);
else
$display ("ERROR");
#10;
end
end
end
endmodule
For some reason when I run my testbench, the outer for loop (A) doesn't iterate values at all. Also, I placed this loop into an initial statement so it will only iterate all the way through once, but it continues to run until I end the simulation.
Here is some sample output:
# 0 is less than 2
# 0 is less than 3
# 0 is less than 4
# 0 is less than 5
# 0 is less than 6
# 0 is less than 7
# 0 is less than 8
# 0 is less than 9
# 0 is less than 10
# 0 is less than 11
# 0 is less than 12
# 0 is less than 13
# 0 is less than 14
# 0 is less than 15
# ERROR
# ERROR
# 0 is less than 2
# 0 is less than 3
# 0 is less than 4
# 0 is less than 5
# 0 is less than 6
# 0 is less than 7
# 0 is less than 8
# 0 is less than 9
# 0 is less than 10
# 0 is less than 11
# 0 is less than 12
# 0 is less than 13
# 0 is less than 14
# 0 is less than 15
# ERROR
# ERROR
# 0 is less than 2
# 0 is less than 3
# 0 is less than 4
# 0 is less than 5
# 0 is less than 6
# 0 is less than 7
# 0 is less than 8
# 0 is less than 9
any ideas what's going on? Thanks
Your problem is in these statements:
reg[3:0] A, B;
...
for (B = 0; B < 16; B = B + 1)
since B is '4' bits wide, it will never be greater or equal to 16. When it gets 15 (4'b1111), the next increment will overflow and make it '0'.
You need make B wider than 4 bits.

awk skipping records. getline command

this is a task related to data compression using fibonacci binary representation.
what i have is this text file:
result.txt
a 20
b 18
c 18
d 15
e 7
this file is a result of scanning a text file and counting the appearances of each char on the file using awk.
now i need to give each char its fibonacci-binary representation length.
since i'm new to ubuntu and teminal, i've done a program in java that receives a number and prints all the fibonacci codewords length up to the number and it's working.
this is exactly what i'm trying to do here. the problem is that it doesn't work...
the length of fibonacci codewords is also work as fibonnaci.
these are the rules:
f(1)=1 - there is 1 codeword of length 1.
f(2)=1 - there is 1 codeword of length 2.
f(3)=2 - there is 2 codeword of length 3.
f(4)=3 - there is 3 codeword of length 4.
and so on...
(i'm adding on more bit to each codeword so the first two lengths will be 2 and 3)
this is the code i've made: its name is scr5
{
a=1;
b=1;
len=2
print $1 , $2, len;
getline;
print $1 ,$2, len+1;
getline;
len=4;
for(i=1; i< num; i++){
c= a+b;
g=c;
while (c >= 1){
print $1 ,$2, len ;
if (getline<=0){
print "EOF"
exit;
}
c--;
i++;
}
a=b;
b=c;
len++;
}}
now i write on terminal:
n=5
awk -v num=$n -f scr5 a
and there are two problems:
1. it skips the third letter c.
2. on the forth letter d, it prints the length of the first letter, 2, instead of length 3.
i guess that there is a problem in the getline command.
thank u very much!
Search Google for getline and awk and you'll mostly find reasons to avoid getline completely! Often it's a sign you're not really doing things the "awk" way. Find an awk tutorial and work through the basics and I'm sure you'll see quickly why your attempt using getlines is not getting you off in the right direction.
In the script below, the BEGIN block is run once at the beginning before any input is read, and then the next block is automatically run once for each line of input --- without any need for getline.
Good luck!
$ cat fib.awk
BEGIN { prior_count = 0; count = 1; len = 1; remaining = count; }
{
if (remaining == 0) {
temp = count;
count += prior_count;
prior_count = temp;
remaining = count;
++len;
}
print $1, $2, len;
--remaining;
}
$ cat fib.txt
a 20
b 18
c 18
d 15
e 7
f 0
g 0
h 0
i 0
j 0
k 0
l 0
m 0
$ awk -f fib.awk fib.txt
a 20 1
b 18 2
c 18 3
d 15 3
e 7 4
f 0 4
g 0 4
h 0 5
i 0 5
j 0 5
k 0 5
l 0 5
m 0 6
The above solution, compressed form :
mawk 'BEGIN{ ___= __= _^=____=+_ } !_ { __+=(\
____=___+_*(_=___+=____))^!_ } $++NF = (_--<_)+__' fib.txt
a 20 1
b 18 2
c 18 3
d 15 3
e 7 4
f 0 4
g 0 4
h 0 5
i 0 5
j 0 5
k 0 5
l 0 5
m 0 6

Is it possible to break in GDB only with the condition, not associated with a line, func, etc? [duplicate]

I like to make GDB set a break point when a variable equal some value I set, I tried this example:
#include <stdio.h>
main()
{
int i = 0;
for(i=0;i<7;++i)
printf("%d\n", i);
return 0;
}
Output from GDB:
(gdb) break if ((int)i == 5)
No default breakpoint address now.
(gdb) run
Starting program: /home/SIFE/run
0
1
2
3
4
5
6
Program exited normally.
(gdb)
Like you see, GDB didn't make any break point, is this possible with GDB?
in addition to a watchpoint nested inside a breakpoint
you can also set a single breakpoint on the 'filename:line_number' and use a condition.
I find it sometimes easier.
(gdb) break iter.c:6 if i == 5
Breakpoint 2 at 0x4004dc: file iter.c, line 6.
(gdb) c
Continuing.
0
1
2
3
4
Breakpoint 2, main () at iter.c:6
6 printf("%d\n", i);
If like me you get tired of line numbers changing, you can add a label
then set the breakpoint on the label like so:
#include <stdio.h>
main()
{
int i = 0;
for(i=0;i<7;++i) {
looping:
printf("%d\n", i);
}
return 0;
}
(gdb) break main:looping if i == 5
You can use a watchpoint for this (A breakpoint on data instead of code).
You can start by using watch i.
Then set a condition for it using condition <breakpoint num> i == 5
You can get the breakpoint number by using info watch
First, you need to compile your code with appropriate flags, enabling debug into code.
$ gcc -Wall -g -ggdb -o ex1 ex1.c
then just run you code with your favourite debugger
$ gdb ./ex1
show me the code.
(gdb) list
1 #include <stdio.h>
2 int main(void)
3 {
4 int i = 0;
5 for(i=0;i<7;++i)
6 printf("%d\n", i);
7
8 return 0;
9 }
break on lines 5 and looks if i == 5.
(gdb) b 5
Breakpoint 1 at 0x4004fb: file ex1.c, line 5.
(gdb) rwatch i if i==5
Hardware read watchpoint 5: i
checking breakpoints
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00000000004004fb in main at ex1.c:5
breakpoint already hit 1 time
5 read watchpoint keep y i
stop only if i==5
running the program
(gdb) c
Continuing.
0
1
2
3
4
Hardware read watchpoint 5: i
Value = 5
0x0000000000400523 in main () at ex1.c:5
5 for(i=0;i<7;++i)
There are hardware and software watchpoints. They are for reading and for writing a variable. You need to consult a tutorial:
http://www.unknownroad.com/rtfm/gdbtut/gdbwatch.html
To set a watchpoint, first you need to break the code into a place where the varianle i is present in the environment, and set the watchpoint.
watch command is used to set a watchpoit for writing, while rwatch for reading, and awatch for reading/writing.

R - Making loops faster

This little code snippet is supposed to loop through a sorted data frame. It keeps a count of how many successive rows have the same information in columns aIndex and cIndex and also bIndex and dIndex. If these are the same, it deposits the count and increments it for the next time around, and if they differ, it deposits the count and resets it to 1 for the next time around.
for (i in 1:nrow(myFrame)) {
if (myFrame[i, aIndex] == myFrame[i, cIndex] &
myFrame[i, bIndex] == myFrame[i, dIndex]) {
myFrame[i, eIndex] <- count
count <- (count + 1)
} else {
myFrame[i, eIndex] <- count
count <- 1
}
}
It's been running for a long time now. I understand that I'm supposed to vectorize whenever possible, but I'm not really seeing it here. What am I supposed to do to make this faster?
Here's what an example few rows should look like after running:
aIndex bIndex cIndex dIndex eIndex
1 2 1 2 1
1 2 1 2 2
1 2 4 8 3
4 8 1 4 1
1 4 1 4 1
I think this will do what you want; the tricky part is that the count resets after the difference, which effectively puts a shift on the eIndex.
There (hopefully) is an easier way to do this, but this is what I came up with.
tmprle <- rle(((myFrame$aIndex == myFrame$cIndex) &
(myFrame$bIndex == myFrame$dIndex)))
myFrame$eIndex <- c(1,
unlist(ifelse(tmprle$values,
Vectorize(seq.default)(from = 2,
length = tmprle$lengths),
lapply(tmprle$lengths,
function(x) {rep(1, each = x)})))
)[-(nrow(myFrame)+1)]
which gives
> myFrame
aIndex bIndex cIndex dIndex eIndex
1 1 2 1 2 1
2 1 2 1 2 2
3 1 2 4 8 3
4 4 8 1 4 1
5 1 4 1 4 1
Maybe this will work. I have reworked the rle and sequence bits.
dat <- read.table(text="aIndex bIndex cIndex dIndex
1 2 1 2
1 2 1 2
1 2 4 8
4 8 1 4
1 4 1 4", header=TRUE, as.is=TRUE,sep = " ")
dat$eIndex <-NA
#identify rows where a=c and b=d, multiply by 1 to get a numeric vector
dat$id<-(dat$aIndex==dat$cIndex & dat$bIndex==dat$dIndex)*1
#identify sequence
runs <- rle(dat$id)
#create sequence, multiply by id to keep only identicals, +1 at the end
count <-sequence(runs$lengths)*dat$id+1
#shift sequence down one notch, start with 1
dat$eIndex <-c(1,count[-length(count)])
dat
aIndex bIndex cIndex dIndex eIndex id
1 1 2 1 2 1 1
2 1 2 1 2 2 1
3 1 2 4 8 3 0
4 4 8 1 4 1 0
5 1 4 1 4 1 1

Code-golf: generate pascal's triangle

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
Generate a list of lists (or print, I don't mind) a Pascal's Triangle of size N with the least lines of code possible!
Here goes my attempt (118 characters in python 2.6 using a trick):
c,z,k=locals,[0],'_[1]'
p=lambda n:[len(c()[k])and map(sum,zip(z+c()[k][-1],c()[k][-1]+z))or[1]for _ in range(n)]
Explanation:
the first element of the list comprehension (when the length is 0) is [1]
the next elements are obtained the following way:
take the previous list and make two lists, one padded with a 0 at the beginning and the other at the end.
e.g. for the 2nd step, we take [1] and make [0,1] and [1,0]
sum the two new lists element by element
e.g. we make a new list [(0,1),(1,0)] and map with sum.
repeat n times and that's all.
usage (with pretty printing, actually out of the code-golf xD):
result = p(10)
lines = [" ".join(map(str, x)) for x in result]
for i in lines:
print i.center(max(map(len, lines)))
output:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
K (Wikipedia), 15 characters:
p:{x{+':x,0}\1}
Example output:
p 10
(1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1)
It's also easily explained:
p:{x {+':x,0} \ 1}
^ ^------^ ^ ^
A B C D
p is a function taking an implicit parameter x.
p unfolds (C) an anonymous function (B) x times (A) starting at 1 (D).
The anonymous function simply takes a list x, appends 0 and returns a result by adding (+) each adjacent pair (':) of values: so e.g. starting with (1 2 1), it'll produce (1 2 1 0), add pairs (1 1+2 2+1 1+0), giving (1 3 3 1).
Update: Adapted to K4, which shaves off another two characters. For reference, here's the original K3 version:
p:{x{+':0,x,0}\1}
J, another language in the APL family, 9 characters:
p=:!/~#i.
This uses J's builtin "combinations" verb.
Output:
p 10
1 1 1 1 1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9
0 0 1 3 6 10 15 21 28 36
0 0 0 1 4 10 20 35 56 84
0 0 0 0 1 5 15 35 70 126
0 0 0 0 0 1 6 21 56 126
0 0 0 0 0 0 1 7 28 84
0 0 0 0 0 0 0 1 8 36
0 0 0 0 0 0 0 0 1 9
0 0 0 0 0 0 0 0 0 1
Haskell, 58 characters:
r 0=[1]
r(n+1)=zipWith(+)(0:r n)$r n++[0]
p n=map r[0..n]
Output:
*Main> p 5
[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1]]
More readable:
-- # row 0 is just [1]
row 0 = [1]
-- # row (n+1) is calculated from the previous row
row (n+1) = zipWith (+) ([0] ++ row n) (row n ++ [0])
-- # use that for a list of the first n+1 rows
pascal n = map row [0..n]
69C in C:
f(int*t){int*l=t+*t,*p=t,r=*t,j=0;for(*t=1;l<t+r*r;j=*p++)*l++=j+*p;}
Use it like so:
int main()
{
#define N 10
int i, j;
int t[N*N] = {N};
f(t);
for (i = 0; i < N; i++)
{
for (j = 0; j <= i; j++)
printf("%d ", t[i*N + j]);
putchar('\n');
}
return 0;
}
F#: 81 chars
let f=bigint.Factorial
let p x=[for n in 0I..x->[for k in 0I..n->f n/f k/f(n-k)]]
Explanation: I'm too lazy to be as clever as the Haskell and K programmers, so I took the straight forward route: each element in Pascal's triangle can be uniquely identified using a row n and col k, where the value of each element is n!/(k! (n-k)!.
Python: 75 characters
def G(n):R=[[1]];exec"R+=[map(sum,zip(R[-1]+[0],[0]+R[-1]))];"*~-n;return R
Shorter prolog version (112 instead of 164):
n([X],[X]).
n([H,I|T],[A|B]):-n([I|T],B),A is H+I.
p(0,[[1]]):-!.
p(N,[R,S|T]):-O is N-1,p(O,[S|T]),n([0|S],R).
another stab (python):
def pascals_triangle(n):
x=[[1]]
for i in range(n-1):
x.append(list(map(sum,zip([0]+x[-1],x[-1]+[0]))))
return x
Haskell, 164C with formatting:
i l=zipWith(+)(0:l)$l++[0]
fp=map (concatMap$(' ':).show)f$iterate i[1]
c n l=if(length l<n)then c n$' ':l++" "else l
cl l=map(c(length$last l))l
pt n=cl$take n fp
Without formatting, 52C:
i l=zipWith(+)(0:l)$l++[0]
pt n=take n$iterate i[1]
A more readable form of it:
iterateStep row = zipWith (+) (0:row) (row++[0])
pascalsTriangle n = take n $ iterate iterateStep [1]
-- For the formatted version, we reduce the number of rows at the final step:
formatRow r = concatMap (\l -> ' ':(show l)) r
formattedLines = map formatRow $ iterate iterateStep [1]
centerTo width line =
if length line < width
then centerTo width (" " ++ line ++ " ")
else line
centerLines lines = map (centerTo (length $ last lines)) lines
pascalsTriangle n = centerLines $ take n formattedLines
And perl, 111C, no centering:
$n=<>;$p=' 1 ';for(1..$n){print"$p\n";$x=" ";while($p=~s/^(?= ?\d)(\d* ?)(\d* ?)/$2/){$x.=($1+$2)." ";}$p=$x;}
Scheme — compressed version of 100 characters
(define(P h)(define(l i r)(if(> i h)'()(cons r(l(1+ i)(map +(cons 0 r)(append r '(0))))))(l 1 '(1)))
This is it in a more readable form (269 characters):
(define (pascal height)
(define (next-row row)
(map +
(cons 0 row)
(append row '(0))))
(define (iter i row)
(if (> i height)
'()
(cons row
(iter (1+ i)
(next-row row)))))
(iter 1 '(1)))
VBA/VB6 (392 chars w/ formatting)
Public Function PascalsTriangle(ByVal pRows As Integer)
Dim iRow As Integer
Dim iCol As Integer
Dim lValue As Long
Dim sLine As String
For iRow = 1 To pRows
sLine = ""
For iCol = 1 To iRow
If iCol = 1 Then
lValue = 1
Else
lValue = lValue * (iRow - iCol + 1) / (iCol - 1)
End If
sLine = sLine & " " & lValue
Next
Debug.Print sLine
Next
End Function
PHP 100 characters
$v[]=1;while($a<34){echo join(" ",$v)."\n";$a++;for($k=0;$k<=$a;$k++)$t[$k]=$v[$k-1]+$v[$k];$v=$t;}
Ruby, 83c:
def p(n);n>0?(m=p(n-1);k=m.last;m+[([0]+k).zip(k+[0]).map{|x|x[0]+x[1]}]):[[1]];end
test:
irb(main):001:0> def p(n);n>0?(m=p(n-1);k=m.last;m+[([0]+k).zip(k+[0]).map{|x|x[0]+x[1]}]):[[1]];end
=> nil
irb(main):002:0> p(5)
=> [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1]]
irb(main):003:0>
Another python solution, that could be much shorter if the builtin functions had shorter names... 106 characters.
from itertools import*
r=range
p=lambda n:[[len(list(combinations(r(i),j)))for j in r(i+1)]for i in r(n)]
Another try, in prolog (I'm practising xD), not too short, just 164c:
s([],[],[]).
s([H|T],[J|U],[K|V]):-s(T,U,V),K is H+J.
l([1],0).
l(P,N):-M is N-1,l(A,M),append(A,[0],B),s(B,[0|A],P).
p([],-1).
p([H|T],N):-M is N-1,l(H,N),p(T,M).
explanation:
s = sum lists element by element
l = the Nth row of the triangle
p = the whole triangle of size N
VBA, 122 chars:
Sub p(n)
For r = 1 To n
l = "1"
v = 1
For c = 1 To r - 1
v = v / c * (r - c)
l = l & " " & v
Next
Debug.Print l
Next
End Sub
I wrote this C++ version a few years ago:
#include <iostream>
int main(int,char**a){for(int b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0;b<atoi(a[1]);(d|f|h)>1?e*=d>1?--d:1,g*=f>1?--f:1,i*=h>1?--h:1:((std::cout<<(i*g?e/(i*g):1)<<" "?d=b+=c++==b?c=0,std::cout<<std::endl?1:0:0,h=d-(f=c):0),e=d,g=f,i=h));}
The following is just a Scala function returning a List[List[Int]]. No pretty printing or anything. Any suggested improvements? (I know it's inefficient, but that's not the main challenge now, is it?). 145 C.
def p(n: Int)={def h(n:Int):List[Int]=n match{case 1=>1::Nil;case _=>(0::h(n-1) zipAll(h(n-1),0,0)).map{n=>n._1+n._2}};(1 to n).toList.map(h(_))}
Or perhaps:
def pascal(n: Int) = {
def helper(n: Int): List[Int] = n match {
case 1 => 1 :: List()
case _ => (0 :: helper(n-1) zipAll (helper(n-1),0,0)).map{ n => n._1 + n._2 }
}
(1 to n).toList.map(helper(_))
}
(I'm a Scala noob, so please be nice to me :D )
a Perl version (139 chars w/o shebang)
#p = (1,1);
while ($#p < 20) {
#q =();
$z = 0;
push #p, 0;
foreach (#p) {
push #q, $_+$z;
$z = $_
}
#p = #q;
print "#p\n";
}
output starts from 1 2 1
PHP, 115 chars
$t[][]=1;
for($i=1;$i<$n;++$i){
$t[$i][0]=1;
for($j=1;$j<$i;++$j)$t[$i][$j]=$t[$i-1][$j-1]+$t[$i-1][$j];
$t[$i][$i]=1;}
If you don't care whether print_r() displays the output array in the correct order, you can shave it to 113 chars like
$t[][]=1;
for($i=1;$i<$n;++$i){
$t[$i][0]=$t[$i][$i]=1;
for($j=1;$j<$i;++$j)$t[$i][$j]=$t[$i-1][$j-1]+$t[$i-1][$j];}
Perl, 63 characters:
for(0..9){push#z,1;say"#z";#z=(1,map{$z[$_-1]+$z[$_]}(1..$#z))}
My attempt in C++ (378c). Not anywhere near as good as the rest of the posts.. but I'm proud of myself for coming up with a solution on my own =)
int* pt(int n)
{
int s=n*(n+1)/2;
int* t=new int[s];
for(int i=0;i<n;++i)
for(int j=0;j<=i;++j)
t[i*n+j] = (!j || j==i) ? 1 : t[(i-1)*n+(j-1)] + t[(i-1)*n+j];
return t;
}
int main()
{
int n,*t;
std::cin>>n;
t=pt(n);
for(int i=0;i<n;++i)
{
for(int j=0;j<=i;j++)
std::cout<<t[i*n+j]<<' ';
std::cout<<"\n";
}
}
Old thread, but I wrote this in response to a challenge on another forum today:
def pascals_triangle(n):
x=[[1]]
for i in range(n-1):
x.append([sum(i) for i in zip([0]+x[-1],x[-1]+[0])])
return x
for x in pascals_triangle(5):
print('{0:^16}'.format(x))
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]

Resources