-
Notifications
You must be signed in to change notification settings - Fork 1
/
nya.zig
122 lines (102 loc) · 3.68 KB
/
nya.zig
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
const std = @import("std");
const builtin = @import("builtin");
const NyaWrite = @import("nyaffered_writer.zig").NyafferedWriter;
// Eventually make this configurable :3
const nyas = [_][]const u8{ "nya", "nyaa~", "mwrp", "mwrwrwp", "uwu", "owo", "OwO", "UwU", "猫", ">w<", "ehehe~" };
const MaxNya = blk: {
comptime var maxlen: usize = 0;
for (nyas) |nya| {
maxlen = @max(nya.len, maxlen);
}
break :blk maxlen;
};
const NyaTotalPL = blk: {
var sum: usize = 0;
for (nyas) |nya| {
if (nya.len == 0) @compileError("One of the nyas is zero-length.");
sum += 8 * ((nya.len - 1) / 8 + 1);
}
break :blk sum;
};
const nya_buf_cur = blk: {
var buf = [_]u8{' '}**NyaTotalPL;
var cursors = [_]u16{0}**(nyas.len+1);
var cursor = 0;
for (nyas, 0..) |nya, i| {
var steps = (nya.len - 1) / 8 + 1;
const new_cursor = cursor + steps;
@memcpy(buf[8*cursor..8*cursor+nya.len], nya);
cursors[i] = cursor;
cursor = new_cursor;
if (i == nyas.len - 1) {
cursors[i+1] = cursor;
}
}
break :blk .{buf, cursors};
};
const nya_string = nya_buf_cur[0];
const nya_cursor = nya_buf_cur[1];
const nya_lens = blk: {
var lens = [_]u8{0}**nyas.len;
for (nyas, 0..) |nya, i| {
lens[i] = @intCast(nya.len + 1);
}
break :blk lens;
};
var pcg = std.rand.Pcg.init(0);
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
var alloc = gpa.allocator();
fn ltf(context: @TypeOf(.{}), lhs: std.AutoHashMap(usize, usize).Entry, rhs: std.AutoHashMap(usize, usize).Entry) bool {
_ = context;
return lhs.key_ptr.* < rhs.key_ptr.*;
}
pub fn main() !void {
// Classic Zig stuff
const stdout = std.io.getStdOut().writer();
const stderr = std.io.getStdErr().writer();
// Timer for benching during development
var timer = try std.time.Timer.start();
defer {
const time: u64 = timer.read();
const timef: f64 = @floatFromInt(time);
const time_s = timef / std.time.ns_per_s;
stderr.print("\n\nTime elapsed: {d:.4} s\n", .{time_s}) catch {};
}
// Accept a number as an argument, this number specfies the number of nyas
// to print.
const args = try std.process.argsAlloc(alloc);
defer std.process.argsFree(alloc, args);
if (args.len != 2) {
try stderr.print("Usage: {s} <number of nyas>\n", .{args[0]});
return;
}
var nya_num = try std.fmt.parseInt(u64, args[1], 10);
const chunksize = 4096;
// Initialize the special NyafferedWriter, which brings the nyas
var buf_writer = NyaWrite(chunksize, @TypeOf(std.io.getStdOut().writer()))
{ .unbuffered_writer = std.io.getStdOut().writer() };
// Current limitation of zig, cant initialize with pointer value from itself.
buf_writer.init();
while (nya_num > 0) {
const nya_this_iteration = @min(64, nya_num);
var precalc_rng: [64]u8 = undefined;
// Pcg beats by other RNGs by kilometers
pcg.fill(std.mem.sliceAsBytes(precalc_rng[0..]));
for (0..precalc_rng.len) |i| {
precalc_rng[i] = precalc_rng[i] % @as(u8, nyas.len);
}
for (0..nya_this_iteration) |i| {
const choice = precalc_rng[i];
const nyalen = nya_lens[choice];
const cursor = nya_cursor[choice];
const steps = nya_cursor[choice+1] - cursor;
buf_writer.write_fast(nya_string[8*cursor..8*cursor+8*steps], nyalen);
}
nya_num -= nya_this_iteration;
if (buf_writer.end.len < precalc_rng.len * MaxNya + 1) {
try buf_writer.flush();
}
}
try buf_writer.flush();
try stdout.print("\n", .{});
}