~rabbits/fractran

ref: 5821f895c302940cd30001d8ee6467c8b9c326ff fractran/fractran.c -rw-r--r-- 1.9 KiB
5821f895neauoire * 10 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdio.h>

/* 
Copyright (c) 2020 Devine Lu Linvega

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/

typedef struct Fraction {
	unsigned int num, den;
} Fraction;

typedef struct Machine {
	int len;
	Fraction state, program[256];
} Machine;

int
gcd(int a, int b)
{
	if(b == 0)
		return a;
	return gcd(b, a % b);
}

Fraction
Frac(unsigned int num, unsigned int den)
{
	Fraction f;
	unsigned int d = gcd(num, den);
	f.num = num / d;
	f.den = den / d;
	return f;
}

void
printstate(Machine *m)
{
	unsigned int fac = 2, num = m->state.num;
	printf("[%d] ", num);
	while(num > 1) {
		if(num % fac == 0) {
			unsigned int pow = 1;
			printf("r%02u=", fac);
			num /= fac;
			while(!(num % fac)) {
				num /= fac;
				pow++;
			}
			printf("%02u", pow);
			if(num != 1)
				putchar(' ');
		} else
			fac++;
	}
	putchar('\n');
}

void
run(Machine *m)
{
	int i = 0;
	while(i < m->len) {
		Fraction res, *f = &m->program[i++];
		res = Frac(m->state.num * f->num, m->state.den * f->den);
		printf("%u × %u/%u = %u/%u \n",
			m->state.num,
			f->num,
			f->den,
			res.num,
			res.den);
		if(res.den == 1) {
			m->state = res;
			printstate(m);
			i = 0;
		}
	}
}

void
push(Machine *m, char *w)
{
	Fraction f;
	if(!m->state.den) {
		if(sscanf(w, "%u", &m->state.num) > 0)
			m->state.den = 1;
		return;
	}
	if(sscanf(w, "%u/%u", &f.num, &f.den) > 0)
		m->program[m->len++] = f;
}

Machine m;

int
main(void)
{
	int len = 0;
	char c, word[64];
	while((c = fgetc(stdin)) != EOF) {
		if(c == ' ' || c == '\n') {
			word[len] = '\0';
			len = 0;
			push(&m, word);
		} else
			word[len++] = c;
		if(c == '\n')
			break;
	}
	printstate(&m);
	run(&m);
	printstate(&m);
	return 0;
}