Skip to content

Instantly share code, notes, and snippets.

@apua
Last active February 3, 2024 08:15
Show Gist options
  • Save apua/ba746701d4b37318aeba7802782b1efc to your computer and use it in GitHub Desktop.
Save apua/ba746701d4b37318aeba7802782b1efc to your computer and use it in GitHub Desktop.
Pascal's triangle by dynamic programming
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void update(int* buffer, size_t last) {
buffer[last] = 1;
for (size_t k = 1; k < last; k++)
buffer[last-k] += buffer[last-k-1];
}
static void print(int* buffer, size_t last) {
putchar('[');
for (size_t i = 0; i <= last; i++) {
printf("%d", buffer[i]);
if (i != last) {
putchar(',');
putchar(' ');
}
}
putchar(']'); putchar('\n');
}
/******************************/
typedef struct Pascal {
size_t max_length;
int *buffer;
size_t last;
} *Pascal;
Pascal pascal_new(size_t max_length) {
Pascal pascal = malloc(sizeof(struct Pascal));
pascal->buffer = malloc(sizeof(int) * max_length);
return pascal;
}
Pascal pascal_init(size_t max_length) {
Pascal pascal = pascal_new(max_length);
pascal->max_length = max_length;
pascal->last = 0;
return pascal;
}
void pascal_del(Pascal pascal) {
free(pascal->buffer);
free(pascal);
}
typedef struct Item {
int *buffer;
size_t length;
} *Item;
Item item_new(size_t length) {
Item item = malloc(sizeof(struct Item));
item->buffer = malloc(sizeof(int) * length);
return item;
}
void item_del(Item item) {
free(item->buffer);
free(item);
}
void item_print(Item item) {
print(item->buffer, item->length-1);
}
/******************************/
void next(Pascal iter, Item item) {
update(iter->buffer, iter->last);
size_t length = iter->last + 1;
memcpy(item->buffer, iter->buffer, sizeof(int) * length);
item->length = length;
iter->last += 1;
}
Item yield(Pascal iter) {
if (!(iter->last < iter->max_length))
return NULL;
Item item = item_new(iter->last + 1);
next(iter, item);
return item;
}
/******************************/
void print_pascal(size_t rows) {
size_t length = rows;
int buffer[length];
for (size_t last = 0; last < rows; last++) {
update(buffer, last);
print(buffer, last);
}
}
void print_pascal_with_buffer_given(size_t rows) {
size_t max_length = rows;
int row_buffer[max_length], item_buffers[rows][max_length];
struct Item items[rows];
struct Pascal pascal_rows = { max_length, row_buffer, 0 };
for (size_t i = 0; i < rows; i++) {
items[i] = (struct Item) { item_buffers[i], 0 };
next(&pascal_rows, &items[i]);
}
for (size_t i = 0; i < rows; i++)
item_print(&items[i]);
}
void print_pascal_without_buffer_given(size_t rows) {
size_t max_length = rows;
Pascal pascal_rows = pascal_init(max_length);
for (Item item = NULL; (item = yield(pascal_rows)); item_del(item))
item_print(item);
pascal_del(pascal_rows);
}
int main(void) {
print_pascal(1);
print_pascal_with_buffer_given(1);
print_pascal_without_buffer_given(1);
// [1]
print_pascal(5);
print_pascal_with_buffer_given(5);
print_pascal_without_buffer_given(5);
// [1]
// [1, 1]
// [1, 2, 1]
// [1, 3, 3, 1]
// [1, 4, 6, 4, 1]
}
r"""
>>> for r in pascal(rows=1): r
[1]
>>> for r in pascal(rows=3): r
[1]
[1, 1]
[1, 2, 1]
>>> for r in tuple(pascal(rows=5)): r
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
"""
def pascal(*, rows: int) -> tuple[int]:
max_length = rows
buffer = [0] * max_length
for last in range(max_length):
buffer[last] = 1
for k in range(1, last):
buffer[last-k] += buffer[last-k-1]
yield buffer[:last+1]
#[derive(Debug)]
struct Pascal {
max_length: usize,
buffer: Vec<i32>,
last: usize,
}
impl Pascal {
fn rows(n: usize) -> Self {
Pascal { max_length: n, buffer: vec![0; n], last: 0 }
}
}
impl Iterator for Pascal {
type Item = Vec<i32>;
fn next(&mut self) -> Option<Self::Item> {
let (max_length, last, buffer) = (&self.max_length, &mut self.last, &mut self.buffer);
if !(*last < *max_length) {
return None;
}
buffer[*last] = 1;
for k in 1..*last {
buffer[*last-k] += buffer[*last-k-1];
}
let item = Some(buffer[..=*last].to_vec());
*last += 1;
return item;
}
}
fn main() {
for r in Pascal::rows(1) { println!("{r:?}"); }
// [1]
for r in Pascal::rows(3) { println!("{r:?}"); }
// [1]
// [1, 1]
// [1, 2, 1]
for r in Pascal::rows(5).collect::<Vec<_>>() { println!("{r:?}"); }
// [1]
// [1, 1]
// [1, 2, 1]
// [1, 3, 3, 1]
// [1, 4, 6, 4, 1]
}
struct Pascal: Sequence, IteratorProtocol {
let max_length: Int
var buffer: [Int]
var last: Int
init(rows: Int) {
max_length = rows
buffer = Array(repeating: 0, count: rows)
last = 0
}
mutating func next() -> [Int].SubSequence? {
guard last < max_length else {
return nil
}
buffer[last] = 1
for k in stride(from: 1, to: last, by: 1) {
buffer[last-k] += buffer[last-k-1]
}
let item = buffer[...last]
last += 1
return item
}
}
for r in Pascal(rows: 1) { print(r) }
// [1]
for r in Pascal(rows: 3) { print(r) }
// [1]
// [1, 1]
// [1, 2, 1]
for r in Array(Pascal(rows: 5)) { print(r) }
// [1]
// [1, 1]
// [1, 2, 1]
// [1, 3, 3, 1]
// [1, 4, 6, 4, 1]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment