Skip to content

Instantly share code, notes, and snippets.

@jooyunghan
Last active February 2, 2016 09:36
Show Gist options
  • Save jooyunghan/04d5217565c3fac56bae to your computer and use it in GitHub Desktop.
Save jooyunghan/04d5217565c3fac56bae to your computer and use it in GitHub Desktop.
C implementation of look and say sequence
//
// main.c
// ant
//
// Created by Jooyung Han on 1/31/16.
// Copyright © 2016 Jooyung Han. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
typedef long long line;
typedef enum bool {false, true}bool;
#define dprintf(...)
//#define dprintf printf
// --- CONT ---
typedef enum io_mode {
IO_READ, IO_WRITE
} io_mode;
typedef struct cont_t {
int cont;
io_mode mode;
char value;
} cont_t;
void print_block_state(int ps, cont_t s) {
dprintf("%d:", ps);
if (s.mode == IO_READ)
dprintf("READ\n");
else
dprintf("WRITE(%d)\n", s.value);
}
cont_t Read(int cont) {
cont_t s = { cont, IO_READ };
return s;
}
cont_t Write(char value, int cont) {
cont_t s = { cont, IO_WRITE, value };
return s;
}
// --- PROC ---
typedef cont_t (*PROC)(int cont, void*, char);
typedef struct proc {
PROC f;
int cont;
void* state;
} proc;
proc* new_proc(PROC f, void* state) {
proc* p = malloc(sizeof(proc));
p->f = f;
p->state = state;
p->cont = 0;
return p;
}
cont_t proc_run(proc* self, char in) {
cont_t c = self->f(self->cont, self->state, in);
self->cont = c.cont;
return c;
}
// --- PIPE ---
typedef struct pipe {
proc** ps;
line size;
} pipe;
pipe* new_pipe(line capa) {
pipe* p = malloc(sizeof(pipe));
p->ps = malloc(sizeof(proc*) * capa);
p->size = 0;
return p;
}
void pipe_add(pipe* self, proc* p) {
self->ps[self->size++] = p;
}
void pipe_run(pipe* self) {
line i = self->size - 1;
char in = 0;
while (true) {
cont_t c = proc_run(self->ps[i], in);
print_block_state(i, c);
if (c.mode == IO_WRITE) {
if (i == self->size - 1) {
if (c.value == 0) {
return;
} else {
printf("%d", c.value);
}
} else {
i++;
in = c.value;
}
} else {
i--;
}
}
}
// --- ANT ---
typedef struct int_state {
line state;
} int_state;
int_state* new_int_state(line n) {
int_state* s = malloc(sizeof(int_state));
s->state = n;
return s;
}
cont_t init(int cont, int_state* s, char x) {
switch (cont) {
case 0:
return Write(1, cont + 1);
default:
return Write(0, cont);
}
}
enum {
ANT_START = 0,
ANT_READ0,
ANT_READ1,
ANT_WRITE_COUNT,
ANT_WRITE_N,
ANT_WRITE_COUNT_END,
ANT_WRITE_N_END,
ANT_WRITE_END
};
typedef struct ant_state {
char n;
char count;
char old_n;
char old_count;
} ant_state;
ant_state* new_ant_state() {
ant_state* s = malloc(sizeof(ant_state));
return s;
}
cont_t ant(int cont, ant_state* s, char in) {
dprintf("next:%d,%d\n", cont, in);
switch (cont) {
case ANT_START:
return Read(ANT_READ0);
case ANT_READ0:
s->n = in;
s->count = 1;
return Read(ANT_READ1);
case ANT_READ1:
if (s->n == in) {
s->count++;
return Read(cont);
} else if (in == 0) {
return Write(s->count, ANT_WRITE_COUNT_END);
} else {
s->old_count = s->count;
s->old_n = s->n;
s->count = 1;
s->n = in;
return Write(s->old_count, ANT_WRITE_COUNT);
}
case ANT_WRITE_COUNT:
return Write(s->old_n, ANT_WRITE_N);
case ANT_WRITE_N:
return Read(ANT_READ1);
case ANT_WRITE_COUNT_END:
return Write(s->n, ANT_WRITE_N_END);
case ANT_WRITE_N_END:
return Write(0, ANT_WRITE_END);
//case ANT_WRITE_END:
default:
return Write(0, cont);
}
}
cont_t nth(int cont, int_state* s, line in) {
switch (cont) {
case 0:
return Read(1);
case 1: {
if (s->state == 0) {
return Write(in, 2);
} else {
s->state--;
return Read(1);
}
}
default:
return Write(0, cont);
}
}
#define N 1000000
#define M 1000000
int main(int argc, const char * argv[]) {
pipe *p = new_pipe(N + 2);
pipe_add(p, new_proc((PROC) init, new_int_state(0)));
for (line i = 0; i < N; i++) {
pipe_add(p, new_proc((PROC) ant, new_ant_state()));
}
pipe_add(p, new_proc((PROC) nth, new_int_state(M)));
pipe_run(p);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment