~rabbits/fractran

ref: 8680f6d04c28d8689ace30323de75b01bf6fd941 fractran/fractran.c -rw-r--r-- 1.9 KiB
8680f6d0neauoire Fixed typo 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 acc, 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->acc.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->acc.num * f->num, m->acc.den * f->den);
		printf("%u × %u/%u = %u/%u \n",
			m->acc.num,
			f->num,
			f->den,
			res.num,
			res.den);
		if(res.den == 1) {
			m->acc = res;
			printstate(m);
			i = 0;
		}
	}
}

void
push(Machine *m, char *w)
{
	Fraction f;
	if(!m->acc.den) {
		if(sscanf(w, "%u", &m->acc.num) > 0)
			m->acc.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;
}