Last active
February 2, 2016 09:36
-
-
Save jooyunghan/04d5217565c3fac56bae to your computer and use it in GitHub Desktop.
C implementation of look and say sequence
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // 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