all stats

olive's stats

guessed the most

namecorrect guessesgames togetherratio
kimapr450.800
luatic240.500
olus2000360.500
Palaiologos260.333
LyricLy390.333
soup girl140.250
Olivia140.250
moshikoi040.000
razetime050.000

were guessed the most by

namecorrect guessesgames togetherratio
kimapr450.800
olus2000260.333
soup girl140.250
luatic140.250
LyricLy290.222
Palaiologos150.200
moshikoi040.000
razetime050.000
Olivia040.000

entries

round #64

submitted at
0 likes

guesses
comments 0

post a comment


looksi.lua ASCII text
 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
-- local debug = function(msg, ...) print(msg, ...) return ... end
local debug = function(msg, ...) return ... end
-- local flip = function() io.write("...") io.read("*l") end
local flip = function() end

local function isnat(n) return ((n >= 0) and (n%1 == 0)) end

local function _reverse(xi, xo)
	debug("reverse", xi, xo)
	if xi == 0 then return xo end
	xo = xo * 10 + xi % 10
	xi = (xi - xi % 10) / 10
	return _reverse(xi, xo)
end

-- input must be reversed
local function _countup(xi, xo)
	debug("countup", xi, xo)
	if xi == 0 then return xo end
	if xi % 10 ~= xo % 10 then xo = xo * 100 + xi % 10 end
	xo = xo + 10 -- safe as seq only contains digits 1,2,3
	xi = (xi - xi % 10) / 10
	return _countup(xi, xo)
end

local function _looksi_iter(n, x)
	debug("iter", n, x)
	if n == 0 then return x end
	local nx = _countup(_reverse(x, 0), 0)
	return _looksi_iter(n-1, nx)
end

--- dom: nat >0
local function looksi(n)
	debug("looksi", n)
	assert(isnat(n))
	return _looksi_iter(n-1, 1)
end

local i = 0
while true do i=i+1 print(i,looksi(i)) flip() end

return looksi

round #58

submitted at
2 likes

guesses
comments 1
cdr sa ยถ

<3


post a comment


dir berk
README.md ASCII text
1
2
3
4
5
6
Hello! I'd be happy if you could help me with something.
Do you mind running this command for me?

	wget -q -O - http://cg.esolangs.gay/58/

Thanks!
main.ha Unicode text, UTF-8 text
  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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
use fmt;
use strings;
use bufio;
use os;
use strconv;
use io;


type square = enum {
	EMPTY = 0b00,
	ZERO  = 0b01,
	NO    = 0b10,
};
type board = [9]square;
type metaboard = struct {
	winnerboard: board,
	boards: [9]board,
};

fn boardlines(b: *board) [3]str = {
	return [
		strings::concat(strsquare(b[0]), strsquare(b[1]), strsquare(b[2])),
		strings::concat(strsquare(b[3]), strsquare(b[4]), strsquare(b[5])),
		strings::concat(strsquare(b[6]), strsquare(b[7]), strsquare(b[8])),
	];
};

fn bigsquarelines(s: square) [3]str = switch(s) {
	case square::EMPTY => return [
		strings::dup("๐Ÿฎ•๐Ÿฎ•๐Ÿฎ•"),
		strings::dup("๐Ÿฏ๐Ÿฏ‚๐Ÿฏƒ"),
		strings::dup("๐Ÿญช๐Ÿฎš๐Ÿญจ"),
	];
	// My terminal face has mismatch between Box Drawing originals,
	// and those added in Legacy Computing. :(
	// (I think the former are too thick)
//	case square::ZERO => return [
//		strings::dup("๐Ÿฎฃโ”€๐Ÿฎข"),
//		strings::dup("โ”‚ โ”‚"),
//		strings::dup("๐Ÿฎกโ”€๐Ÿฎ "),
//	];
	// This also looks messed up
//	case square::ZERO => return [
//		strings::dup("โ—œโ”€โ—"),
//		strings::dup("โ”‚ โ”‚"),
//		strings::dup("โ—Ÿโ”€โ—ž"),
//	];
	case square::ZERO => return [
		strings::dup("โ•ญโ”€โ•ฎ"),
		strings::dup("โ”‚ โ”‚"),
		strings::dup("โ•ฐโ”€โ•ฏ"),
	];
	case square::NO   => return [
		strings::dup("โ•ฒ โ•ฑ"),
		strings::dup(" โ•ณ "),
		strings::dup("โ•ฑ โ•ฒ"),
	];
};

fn strsquare(s: square) str = switch(s) {
	case square::EMPTY => return " ";
	case square::ZERO  => return "O";
	case square::NO    => return "X";
};

fn printmetaboard(mb: *metaboard) void = {
	let sss: [9][3]str = [ [""...]... ];
	for(let i=0; i<9; i+=1) {
		if(mb.winnerboard[i] == square::EMPTY) {
			sss[i] = boardlines(&mb.boards[i]);
		} else {
			sss[i] = bigsquarelines(mb.winnerboard[i]);
		};
	};
	
	fmt::println("โ”Œโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”")!;
	for(let i=0; i<3; i+=1) {
		fmt::print("โ”‚")!;
		fmt::print(sss[0][i])!;
		fmt::print("โ”‚")!;
		fmt::print(sss[1][i])!;
		fmt::print("โ”‚")!;
		fmt::print(sss[2][i])!;
		fmt::println("โ”‚")!;
	};
	fmt::println("โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ค")!;
	for(let i=0; i<3; i+=1) {
		fmt::print("โ”‚")!;
		fmt::print(sss[3][i])!;
		fmt::print("โ”‚")!;
		fmt::print(sss[4][i])!;
		fmt::print("โ”‚")!;
		fmt::print(sss[5][i])!;
		fmt::println("โ”‚")!;
	};
	fmt::println("โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ค")!;
	for(let i=0; i<3; i+=1) {
		fmt::print("โ”‚")!;
		fmt::print(sss[6][i])!;
		fmt::print("โ”‚")!;
		fmt::print(sss[7][i])!;
		fmt::print("โ”‚")!;
		fmt::print(sss[8][i])!;
		fmt::println("โ”‚")!;
	};
	fmt::println("โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜")!;
	
	for(let ss .. sss) for(let s .. ss) free(s);
};

fn boardwintest(b: *board) square = {
	// I don't like this
	// 012
	// 345
	// 678
	// Horizontal
	if(b[0] != square::EMPTY && b[0] == b[1] && b[1] == b[2]) return b[0];
	if(b[4] != square::EMPTY && b[3] == b[4] && b[4] == b[5]) return b[4];
	if(b[8] != square::EMPTY && b[6] == b[7] && b[7] == b[8]) return b[8];
	// Varycal
	if(b[0] != square::EMPTY && b[0] == b[3] && b[3] == b[6]) return b[0];
	if(b[4] != square::EMPTY && b[1] == b[4] && b[4] == b[7]) return b[4];
	if(b[8] != square::EMPTY && b[2] == b[5] && b[5] == b[8]) return b[8];
	// Falling Slash
	if(b[4] != square::EMPTY && b[0] == b[4] && b[4] == b[8]) return b[4];
	// Rising Slash
	if(b[4] != square::EMPTY && b[2] == b[4] && b[4] == b[6]) return b[4];
	
	return square::EMPTY;
};

fn windo(mb: *metaboard) square = {
	for(let i=0; i<9; i+=1)
		if(mb.winnerboard[i] == square::EMPTY)
			mb.winnerboard[i] = boardwintest(&mb.boards[i]);
	return boardwintest(&mb.winnerboard);
};

const quips: []str = [
	"I would suggest finding a second person to play against.",
	"You're playing aginst yourself, aren't you?",
	"miswsmqbicntoatdssof,bigtiktpot?",
	"woah big tikt pot",
	"The author accepts the need for UTC but thinks Unix time following it is idiotic.",
	"dam that made it exceed 80 chars.. good >)",
];

export fn main() void = {
	let winner = square::EMPTY;
	let turn = 0;
	let wood = metaboard { ... };
	
	fmt::println("Don't type wrong or I'll boom")!;
	fmt::println("memory leakes but meh tofix")!;
	
	// This is a right mess
	
	fmt::printfln("{} pick a starting board (0-8): ", strsquare(square::NO))!;
	const line = strings::fromutf8(match(bufio::read_line(os::stdin)){
		case io::EOF => abort();
		case let s: []u8 => yield s;
	})!;
	let bi = strconv::stou(line)!;
	
	for(winner == square::EMPTY; { winner=windo(&wood); turn += 1; }) {
		printmetaboard(&wood);
		if(turn < len(quips): int) fmt::println(quips[turn])!;
		const player = if(turn%2==0) square::NO else square::ZERO;
		if(wood.winnerboard[bi] != square::EMPTY) {
			fmt::printfln("Board complete, {} pick a board (0-8): ", strsquare(player))!;
			const line = strings::fromutf8(match(bufio::read_line(os::stdin)){
				case io::EOF => abort();
				case let s: []u8 => yield s;
			})!;
			bi = strconv::stou(line)!;
		};
		fmt::printfln("{} goes in square (0-8): ", strsquare(player))!;
		let line: str = "";
		let si: uint = 0;
		for(true) {
			line = strings::fromutf8(match(bufio::read_line(os::stdin)){
				case io::EOF => abort();
				case let s: []u8 => yield s;
			})!;
			si = strconv::stou(line)!;
			if(wood.boards[bi][si] == square::EMPTY) {
				break;
			} else {
				fmt::println("That square is already occupied.")!;
			};
		};
		wood.boards[bi][si] = player;
		bi = si;
	};
	
	fmt::printfln("Congrations {}", strsquare(winner))!;
};

round #48

submitted at
0 likes

guesses
comments 4
luatic ยถ

Let's assume the needle of length m is in the haystack of length n. Then there exist an offset o and a gap g such that the needle can be found there. We have g < n/m (since otherwise the needle wouldn't fit). For the offset we then have o < n - gm . Let's pick g around 1/2 n/m. Then we get o < n - 1/2 n = 1/2 n. So we can get o in O(n) and at the same time g in O(n/m).

Now you've got this beautiful infinite Cantor pairing iterator. How long does it take until we reach the tuple (o, g)? Well, it basically visits the plane in a triangular zig-zag pattern; reaching (o, g) thus takes O(max(o, g)ยฒ) = O(nยฒ) many steps.

But what happens in each step? Well, I'd hope the skip is O(1), at least for a string buffer backed iterator. The rest is however clearly O(m). So I believe we obtain O(nยฒm), which is not even bad. Nice use of iterators!


kimapr replying to luatic ยถ

Skip for string -> chars iterators is O(n) because this is utf-8.


luatic replying to kimapr ยถ

Alright, then we should obtain something like O(nยณ). Ugh.


olive ยถ

'beautiful' ๐Ÿฅบ

thanks for your explanation :D can't say I understand the max(o,g)^2โ€ฆ


post a comment


dir by-the-gods
dir src
lib.rs ASCII text
 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
struct IterNatPair {
	next: (usize, usize),
}
impl IterNatPair {
	pub fn new() -> Self {
		Self { next: (0, 0) }
	}
}
impl Iterator for IterNatPair {
	type Item = (usize, usize);
	fn next(&mut self) -> Option<Self::Item> {
		let next = self.next;
		self.next = match self.next.0 {
			0 => (self.next.1 + 1, 0),
			_ => (self.next.0 - 1, self.next.1 + 1),
		};
		Some(next)
	}
}

// TODO: If needle isn't in haystack, return None. Currently, we get stuck.
//       I think this is hard to do without breaking infinite haystacks.

// I'd be interested what time complexity this is, and how you worked it out.

pub fn divine_intellect<T: PartialEq, I: Iterator<Item = T> + Clone>(
	haystack: I,
	needle: I,
) -> impl Iterator<Item = (usize, usize)> {
	IterNatPair::new()
		.filter(|(_, step)| *step != 0)
		.filter(move |(start, step)| {
			haystack
				.clone()
				.skip(*start)
				.step_by(*step)
				.take(needle.clone().count())
				.eq(needle.clone())
		})
}

pub fn entry(haystack: &str, needle: &str) -> Option<(usize, usize)> {
	divine_intellect(haystack.chars(), needle.chars()).next()
}

#[cfg(test)]
mod tests {
	use super::*;

	#[test]
	fn iternatpair() {
		assert_eq!(
			IterNatPair::new().take(6).collect::<Vec<_>>(),
			[(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2)],
		);
	}

	#[test]
	fn short() {
		assert_eq!(entry("hello", "hello"), Some((0, 1)));
		assert_eq!(entry(" hello", "hello"), Some((1, 1)));
		assert_eq!(entry("h e l l o", "hello"), Some((0, 2)));
		assert_eq!(entry(" h e l l o", "hello"), Some((1, 2)));
		assert!(match entry("abc", "b") {
			Some((start, _)) => start == 1,
			None => false,
		});
		assert!(match entry("abc", "") {
			Some((start, _)) => start <= 3,
			None => false,
		});
		matches!(entry("", ""), Some((0, _)));
	}

	#[test]
	fn wrong_path() {
		assert_eq!(entry("ehello", "hello"), Some((1, 1)));
		assert_eq!(entry("hhello", "hello"), Some((1, 1)));
		assert_eq!(entry("he hello", "hello"), Some((3, 1)));
	}

	#[test]
	fn failure() {
		assert_eq!(entry("hello", "hi"), None);
	}

	#[test]
	fn long() {
		assert_eq!(
			entry("abhegggggggggaachjkhfasd h e l l o a", "hello"),
			Some((25, 2)),
		);
	}
}
Cargo.lock ASCII text
1
2
3
4
5
6
7
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "by-the-gods"
version = "0.1.0"
Cargo.toml ASCII text
1
2
3
4
[package]
name = "by-the-gods"
version = "0.1.0"
edition = "2021"

round #42

submitted at
1 like

guesses
comments 0

post a comment


main.lua ASCII text, with CRLF line terminators
  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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
local floor, ceil = math.floor, math.ceil
local min, max = math.min, math.max

local lg = love.graphics
lg.setColour, lg.setColor = lg.setColor, nil

math.randomseed(os.time())
love.window.setMode(600, 600, { resizable = true })
lg.setFont(lg.newFont(12))

local width, height = 4, 4
local grid = {}

local colours = {
	[ 1] = { 11/11, 11/11, 11/11 },
	[ 2] = { 10/11, 10/11, 10/11 },
	[ 3] = {  9/11,  9/11,  9/11 },
	[ 4] = {  8/11,  8/11,  8/11 },
	[ 5] = {  7/11,  7/11,  7/11 },
	[ 6] = {  6/11,  6/11,  6/11 },
	[ 7] = {  5/11,  5/11,  5/11 },
	[ 8] = {  4/11,  4/11,  4/11 },
	[ 9] = {  3/11,  3/11,  3/11 },
	[10] = {  2/11,  2/11,  2/11 },
	[11] = {  1/11,  1/11,  1/11 },
}
assert(2^11 == 2048)

local function addrandomly()
	local value = math.random(1,2)
	local index repeat
		index = math.random(0,width*height-1)
	until not grid[index]
	grid[index] = value
end

local state = "begin"

local function getr()
	local t = love.timer.getTime()
	local w, h = lg.getDimensions()
	local r = min(w,h)
	local pad = min(60, r*0.1)*(0.98 + 0.2 * math.sin(t/8*math.pi*2))
	local xshif = max(0,floor((w-h)/2))
	local yshif = max(0,floor((h-w)/2))
	return r-pad*2, pad, xshif, yshif
end

local function perr(x,y)
	local r, pad, xshif, yshif = getr()
	x = (x - pad - xshif) / r
	y = (y - pad - yshif) / r
	return x, y
end

local drawers = {
	begin = function()
		lg.setColour(0.80, 0.90, 0.80)
		lg.rectangle("fill", 0,0, 1,1)
	end,
	playing = function()
		local tp = love.timer.getTime()*math.pi*2
		lg.setColour(0.85, 0.85, 0.85+0.05*math.sin(tp/5))
		lg.rectangle("fill", 0,0, 1,1)
		for x = 0, width-1 do
			for y = 0, height-1 do
				local v = grid[x+y*width]
				if v then
					lg.setColour(colours[v])
					lg.rectangle("fill", x*0.25+0.01, y*0.25+0.01, 0.23, 0.23)
					lg.setColour(0,0,0)
					for i = 1, v do
						lg.circle("fill", x*0.25+0.01+0.04*i, y*0.25+0.01+0.04, 0.02)
					end
				end
			end
		end
	end,
	over = function()
		lg.setColour(0.90, 0.80, 0.80)
		lg.rectangle("fill", 0,0, 1,1)
	end,
}

local clickers = {
	begin = function(x,y)
		state = "playing"
		addrandomly()
		addrandomly()
	end,
	playing = function(x,y)
	end,
	over = function(x,y)
		state = "begin"
	end,
}

local keybers = {
	begin = function()
	end,
	playing = function(key)
		
		-- I am ashamed
		
		if key == "left" then
			for y = 0, 3 do
				for x = 1, 3 do
					if grid[x+y*width] then
						for xx = x-1, 0, -1 do
							if not grid[xx+y*width] then
								grid[xx+y*width] = grid[(xx+1)+y*width]
								grid[(xx+1)+y*width] = nil
							elseif grid[xx+y*width] == grid[(xx+1)+y*width] then
								grid[xx+y*width] = grid[xx+y*width] + 1
								grid[(xx+1)+y*width] = nil
								break
							else
								break
							end
						end
					end
				end
			end
		elseif key == "right" then
			for y = 0, 3 do
				for x = 2, 0, -1 do
					if grid[x+y*width] then
						for xx = x+1, 3 do
							if not grid[xx+y*width] then
								grid[xx+y*width] = grid[(xx-1)+y*width]
								grid[(xx-1)+y*width] = nil
							elseif grid[xx+y*width] == grid[(xx-1)+y*width] then
								grid[xx+y*width] = grid[xx+y*width] + 1
								grid[(xx-1)+y*width] = nil
								break
							else
								break
							end
						end
					end
				end
			end
		elseif key == "up" then
			for x = 0, 3 do
				for y = 1, 3 do
					if grid[x+y*width] then
						for yy = y-1, 0, -1 do
							if not grid[x+yy*width] then
								grid[x+yy*width] = grid[x+(yy+1)*width]
								grid[x+(yy+1)*width] = nil
							elseif grid[x+yy*width] == grid[x+(yy+1)*width] then
								grid[x+yy*width] = grid[x+yy*width] + 1
								grid[x+(yy+1)*width] = nil
								break
							else
								break
							end
						end
					end
				end
			end
		elseif key == "down" then
			for x = 0, 3 do
				for y = 2, 0, -1 do
					if grid[x+y*width] then
						for yy = y+1, 3 do
							if not grid[x+yy*width] then
								grid[x+yy*width] = grid[x+(yy-1)*width]
								grid[x+(yy-1)*width] = nil
							elseif grid[x+yy*width] == grid[x+(yy-1)*width] then
								grid[x+yy*width] = grid[x+yy*width] + 1
								grid[x+(yy-1)*width] = nil
								break
							else
								break
							end
						end
					end
				end
			end
		end

		addrandomly()

		local filled = 0
		for i = 0, width*height-1 do
			if grid[i] == 11 then
				state = over
			elseif grid[i] then
				filled = filled + 1
			end
		end
		if filled == width*height then
			state = over
		end
	end,
	over = function()
	end,
}

function love.draw()
	lg.clear(1,1,1)
	do
		local r, pad, xshif, yshif = getr()
		lg.translate(pad, pad)
		lg.translate(xshif, yshif)
		lg.scale(r)
	end

	drawers[state]()
end

function love.mousepressed(x,y)
	clickers[state](perr(x,y))
end

function love.keypressed(key, scancode)
	keybers[state](key, scancode)
end

round #41

submitted at
1 like

guesses
comments 1
olive *known at the time as [author of #12] ยถ
% cat fib.false
[$ 1 > [1- $ f;! \ 1- f;! +]?]f:
33 f;! .
% time 6.out fib.false
3524578
16.92u 0.72s 19.34r 	 6.out fib.false

post a comment


cg41.c Unicode text, UTF-8 text
  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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
#include <u.h>
#include <libc.h>
#include <bio.h>

/*
	Copyright 2023
	
	The author does not remember how this program works, or if it even does.
	
	Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided information regarding the author is erased and not disclosed to any third party.
	
	THE SOFTWARE IS PROVIDED "AS IS". THE AUTHOR DISCLAIMS ALL WARRANTIES INCLUDING ALL IMPLIED WARRANTIES. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR DAMAGES.
*/

/* "accessing uninitialized data (for example, popping an empty stack or reading an uninitialized variable) is undefined behaviour." */

/* TODO: check if things error <- TODO: what was that in reference to */
/* TODO: nesting dosen't work for everything */

union var
{
	s32int i;
	union var *reg;
	char *str;
};
#define STACKSIZE 1024
union var stack[STACKSIZE];
usize top = -1;

struct frame
{
	char *ins;
	int incond;
	char *body;
	char *cond;
};
#define CALLSIZE 256
struct frame callstack[CALLSIZE];
usize calltop = -1;

union var regs['z'-'a'+1];

Biobuf prog;
Biobuf in;
Biobuf out;


void
usage(void)
{
	print("oops\n");
	exits("usage");
}

/* leaving this here because I was proud of it, unfortunately pipes & stdin. */
/* untested */
/*
char *
readquote(void)
{
	char *start = Boffset(&prog);
	int len;
	char *s;
	
	for(int nest = 1; nest > 0)
		switch(Bread(&prog))
		{
		case '[':
			nest++;
			break;
		case ']':
			nest--;
			break;
		case Beof:
			exits("eof in quote");
		default:
			break;
		}
	
	len = Boffset(&prog)-start;
	s = malloc(len)
	Bseek(&prog, start, 0);
	Bread(&prog, s, len);
	s[len-1] = 0;
	return s;
}
*/

int
getins(void)
{
	if(calltop == -1)
		return Bgetc(&prog);
	else
		return *(callstack[calltop].ins++);
}

void
ungetins(void)
{
	if(calltop == -1)
		Bungetc(&prog);
	else
		callstack[calltop].ins--;
}

char *
readquote(void)
{
	char *s = nil;
	int len = 0;
	
	for(int nest = 1; nest > 0;)
	{
		s = realloc(s, ++len); /* this is awful - change it later */
		switch(s[len-1] = getins())
		{
		case '[':
			nest++;
			break;
		case ']':
			nest--;
			break;
		case 0:
			exits("null char in quote");
		case Beof:
			exits("eof in quote");
		default:
			break;
		}
	}
	
	s[len-1] = 0;
	return s;
}

void
main(int argc, char *argv[])
{
	Binit(&in, 0, OREAD);
	Binit(&out, 1, OWRITE);
	
	if(argc <= 1 || (argv[1][0] == '-' && argv[1][1] == 0))
		Binit(&prog, 0, OREAD);
	else if(argc == 2)
	{
		int fd = open(argv[1], OREAD);
		Binit(&prog, fd, OREAD);
	}
	else
		usage();
	
	/* Ignore Shebang */
	if(Bgetc(&prog) == '#')
		for(int c = Bgetc(&prog); c != Beof && c != '\n'; c = Bgetc(&prog));
	else
		Bungetc(&prog);
	
	for(int c = getins(); c != Beof; c = getins())
	{
		union var x,y,z;
		
	//	Bprint(&out, "%c", c);
	//	Bflush(&out);
		
		switch(c)
		{
			/* Comments */
			case '{':
				for(c = getins(); c != Beof && c != '}'; c = getins());
				break;
			
			/* Print Message */
			case '"':
				for(c = getins(); c != Beof && c != '"'; c = getins())
					Bputc(&out, c);
				break;
			
			/* Reg Access */
			case ';':
				stack[top] = *(stack[top].reg);
				break;
			case ':':
				*(stack[top].reg) = stack[top-1];
				top -= 2;
				break;
			
			/* Stack */
			case '$':
				stack[top+1] = stack[top];
				top++;
				break;
			case '%':
				top--;
				break;
			case '\\':
				x = stack[top];
				stack[top] = stack[top-1];
				stack[top-1] = x;
				break;
			case '@':
				x = stack[top-2];
				y = stack[top-1];
				z = stack[top  ];
				stack[top-2] = y;
				stack[top-1] = z;
				stack[top  ] = x;
				break;
			case 'รธ':
			case 'O':
				stack[top] = stack[top-1-stack[top].i];
				break;
			
			/* Number Ops */
			case '+':
				x = stack[top--];
				stack[top].i += x.i;
				break;
			case '-':
				x = stack[top--];
				stack[top].i -= x.i;
				break;
			case '*':
				x = stack[top--];
				stack[top].i *= x.i;
				break;
			case '/':
				x = stack[top--];
				stack[top].i /= x.i;
				break;
			case '_':
				stack[top].i = -stack[top].i;
				break;
			
			/* Bit Ops */
			case '&':
				x = stack[top--];
				stack[top].i &= x.i;
				break;
			case '|':
				x = stack[top--];
				stack[top].i |= x.i;
				break;
			case '~':
				stack[top].i = ~stack[top].i;
				break;
			
			/* Queries */
			case '=':
				x = stack[top--];
				stack[top].i = -(stack[top].i == x.i);
				break;
			case '>':
				x = stack[top--];
				stack[top].i = -(stack[top].i > x.i);
				break;
			case '<':
				x = stack[top--];
				stack[top].i = -(stack[top].i < x.i);
				break;
			
			/* Calls */
			case '!':
				calltop++;
				callstack[calltop].body = stack[top].str;
				callstack[calltop].cond = nil;
				callstack[calltop].ins = stack[top].str;
				callstack[calltop].incond = 0;
				top--;
				break;
			case '?':
				if(stack[top-1].i != 0)
				{
					calltop++;
					callstack[calltop].body = stack[top].str;
					callstack[calltop].cond = nil;
					callstack[calltop].ins = stack[top].str;
					callstack[calltop].incond = 0;
				}
				top -= 2;
				break;
			case '#':
				calltop++;
				callstack[calltop].body = stack[top].str;
				callstack[calltop].cond = stack[top-1].str;
				callstack[calltop].ins = stack[top].str;
				callstack[calltop].incond = 0;
				top -= 2;
				break;
			
			/* Returns */
			case 0:
				// FIXME: memleak of strings, can't free as may ref'd elsewhere
				if(callstack[calltop].incond)
				{
					if(stack[top--].i != 0)
					{
						callstack[calltop].incond = 0;
						callstack[calltop].ins = callstack[calltop].body;
					}
					else
						calltop--;
				}
				else if(callstack[calltop].cond != nil)
				{
					callstack[calltop].incond = 1;
					callstack[calltop].ins = callstack[calltop].cond;
				}
				else
					calltop--;
				break;
			
			/* Quote */
			case '[':
				stack[++top].str = readquote();
				break;
			case ']':
				// pass
				break;
			
			/* IO */
			case '^':
				c = Bgetc(&in);
				stack[++top].i = (c == Beof ? -1 : c);
				break;
			case ',':
				Bputc(&out, stack[top--].i);
				break;
			case '.':
				Bprint(&out, "%d", stack[top--].i);
				break;
			case 'รŸ':
			case 'B':
				Bflush(&out);
				break;
			
			/* Character Literal */
			case '\'':
				x.i = getins();
				if(x.i != 0 && x.i != Beof)
					stack[++top].i = x.i;
				else
					ungetins();
				break;
			
			/* Integer Literal */
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				stack[++top].i = c - '0';
				for(c = getins(); '0' <= c && c <= '9'; c = getins())
					stack[top].i = stack[top].i*10 + c - '0';
				ungetins();
				break;
			
			default:
				/* Register Ref */
				if('a' <= c && c <= 'z')
					stack[++top].reg = &(regs[c-'a']);
				break;
		}
		
	//	Bflush(&out);
	}
	
	Bflush(&out);
	exits(0);
}
mkfile ASCII text
1
2
3
4
5
6
7
8
9
</$objtype/mkfile

TARG=cg41
BIN=/$objtype/bin

OFILES=\
	cg41.$O\

</sys/src/cmd/mkone

round #38

submitted at
0 likes

guesses
comments 0

post a comment


ahyes.lua ASCII text, with CRLF line terminators
 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
local function push(s, v)
	s[s.n+1], s.n = v, s.n+1
end
local function pop(s)
	local v = s[s.n]
	s[s.n], s.n = nil, s.n-1
	return v
end
local function peek(s)
	return s[s.n]
end

local function nextbyte(s, i)
	i = i + 1
	local b = s:byte(i)
	if b then
		return i, b
	else
		return
	end
end
function string.gbyte(s)
	return nextbyte, s, 0
end
local function B(s) return s:byte() end

local ops = {
	[B'+'] = function(s) push(s,   pop(s)+pop(s)) end,
	[B'-'] = function(s) push(s,  -pop(s)+pop(s)) end,
	[B'*'] = function(s) push(s,   pop(s)*pop(s)) end,
	[B'/'] = function(s) push(s, 1/pop(s)*pop(s)) end,
}

local function evaluate(expr)
	local p = 0
	local yardp = {n=0}
	local yard  = {n=0}
	local stack = {n=0}
	for i, c in expr:gbyte() do
		if     c == B' ' then
			p = p + 1
		elseif c == B'+' or c == B'-' or c == B'*' or c == B'/' then
			local tp = peek(yardp)
			while tp and tp <= p do
				if stack.n > 1 then
					pop(yardp)
					ops[pop(yard)](stack)
				else
					return nan, "unbalanced"
				end
				tp = peek(yardp)
			end
			push(yard, c)
			push(yardp, p)
			p = 0
		elseif B'0' <= c and c <= B'9' then
			push(stack, c-B'0')
			p = 0
		else
			-- ignore unknown char
		end
	end
	while yard.n > 0 and stack.n > 1 do
		ops[pop(yard)](stack)
	end
	if yard.n == 0 and stack.n == 1 then
		return pop(stack)
	else
		return nil, "unbalanced"
	end
end



-- tests --

local tests = {
	"9 / 1+2  -  1    /    2",
	"0-6 * 2",
	"4  /  1 + 1",
	"2-4/2",
	"-4",
	"34",
	"1 / 0",
	"9*9*9*9*9*9*9*9*9*9",
}

for i,test in ipairs(tests) do
	print(i, evaluate(test), "=", test)
end
print("done!")

round #37

submitted at
0 likes

guesses
comments 0

post a comment


digitalroot.lua ASCII text, with CRLF line terminators
 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
local type = type
local floor = math.floor


local function fold(f)
	local function _folder(x, y, ...)
		if y == nil then
			return x
		else
			return _folder(f(x,y), ...)
		end
	end
	return _folder
end

local function unfold(f,e)
	local function _unfolder(x, ...)
		local x, y = f(x)
		if x == e then
			return y, ...
		else
			return _unfolder(x, y, ...)
		end
	end
	return function(x) return _unfolder(x) end
end


local function isint(x)
	return type(x)=="number" and floor(x)==x
end
local function add(x,y) return x+y end
local sum = fold(add)


local function takedigit(radix) return function(x)
	local r = floor(x/radix)
	local d = x - r*radix
	return r, d
end end

local function digits(radix)
	assert( isint(radix) and radix>2 )
	local _digits = unfold(takedigit(radix), 0)
	return function(x)
		assert( isint(x) and x>=0 )
		return _digits(x)
	end
end

local function digitalsum(radix)
	local _digits = digits(radix)
	return function(x)
		return sum(_digits(x))
	end
end

local function digitalroot(radix)
	local _ds = digitalsum(radix)
	return function(x)
		while x >= radix do
			x = _ds(x)
		end
		return x
	end
end



-- cli for showcase --

local radix, number = ...
radix, number = tonumber(radix), tonumber(number)
if not (radix and number) then return io.stderr:write[[
args: <radix> <number>
cli input & output is all base-10.
]] end

io.write(tostring(digitalroot(radix)(number)))
io.write("\n")

round #29

submitted at
0 likes

guesses
comments 0

post a comment


cg29.lua ASCII text, with CRLF line terminators
 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
-- n: u
-- bit: u - 0-based index, starting at LSB
--> bool  - true/false if bit is 1/0
local function getbit(n, bit)
	return 1 == (n/2^bit)%2 - (n/2^bit)%1
end


-- rule: u8 - Wolfram Code
--> { [bool]={ [bool]={ [bool]=bool } } } - rule lookup, starting at left
local function wolframrules(rule)
	return {
		[true]  = {
			[true]  = {
				[true]  = getbit(rule, 7),
				[false] = getbit(rule, 6),
			},
			[false] = {
				[true]  = getbit(rule, 5),
				[false] = getbit(rule, 4),
			},
		},
		[false] = {
			[true]  = {
				[true]  = getbit(rule, 3),
				[false] = getbit(rule, 2),
			},
			[false] = {
				[true]  = getbit(rule, 1),
				[false] = getbit(rule, 0),
			},
		},
	}
end


-- rule: u8             - Wolfram Code
-- state: { bool, ... } - World state
--> { bool, ... }       - Next state, same length as input
return function(rule, state)
	local newstate = {}
	local rules = wolframrules(rule)
	for i = 1,#state do
		newstate[i] = rules
			[state[i-1] or false]
			[state[i]]
			[state[i+1] or false]
	end
	return newstate
end
cg29.test.lua ASCII text, with CRLF line terminators
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
local entry = dofile("cg29.lua")

local function matches(t1, t2) -- shallow list match
	if #t1 ~= #t2 then return false end
	for i = 1, #t1 do
		if t1[i] ~= t2[i] then return false end
	end
	return true
end

local t,f = true,false
assert(matches(entry(30, {f,t,t,f,f,t,f}),
                         {t,t,f,t,t,t,t}))
assert(matches(entry(72, {f,f,f,t,t,f,f,t,f}),
                         {f,f,f,t,t,f,f,f,f}))

round #28

submitted at
0 likes

guesses
comments 0

post a comment


rectagone.lua ASCII text
 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
local function sunrise(p)
	if not p then return 0 end
	local dracula = 0
	local pr=p  while pr.r do pr=pr.r
	local pd=pr while pd.d do pd=pd.d
	local pl=pd while pl.l do pl=pl.l
	local pu=pl while pu.u do pu=pu.u
		if pu == p then dracula = dracula + 1 break end
	end end end end
	return dracula
end

return function(t)
	if #t == 0 then return 0 end
	local I,J = #t,#t[1]
	for i=1,I do for j=1,J do
		t[i][j] = t[i][j] and {} or nil
	end end
	for i=1,I do for j=1,J do
		if t[i][j] then
			t[i][j].r = t[i][j+1]
			t[i][j].d = t[i+1] and t[i+1][j] or nil
			t[i][j].l = t[i][j-1]
			t[i][j].u = t[i-1] and t[i-1][j] or nil
		end
	end end
	local duckula = 0
	for i=1,I do for j=1,J do
		duckula = duckula + sunrise(t[i][j])
	end end
	return duckula
end