Data update

This commit is contained in:
Ingy döt Net 2026-04-30 12:34:36 -04:00
parent 4bb20c9b71
commit cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions

View file

@ -0,0 +1,72 @@
with Ada.Text_Io;
with Ada.Command_Line;
with Ada.Containers.Indefinite_Holders;
procedure Stream_Merge is
package String_Holders
is new Ada.Containers.Indefinite_Holders (String);
use Ada.Text_Io, String_Holders;
type Stream_Type is
record
File : File_Type;
Value : Holder;
end record;
subtype Index_Type is Positive range 1 .. Ada.Command_Line.Argument_Count;
Streams : array (Index_Type) of Stream_Type;
procedure Fetch (Stream : in out Stream_Type) is
begin
Stream.Value := (if End_Of_File (Stream.File)
then Empty_Holder
else To_Holder (Get_Line (Stream.File)));
end Fetch;
function Next_Stream return Index_Type is
Index : Index_Type := Index_Type'First;
Value : Holder;
begin
for I in Streams'Range loop
if Value.Is_Empty and not Streams (I).Value.Is_Empty then
Value := Streams (I).Value;
Index := I;
elsif not Streams (I).Value.Is_Empty and then Streams (I).Value.Element < Value.Element then
Value := Streams (I).Value;
Index := I;
end if;
end loop;
if Value.Is_Empty then
raise Program_Error;
end if;
return Index;
end Next_Stream;
function More_Data return Boolean
is (for some Stream of Streams => not Stream.Value.Is_Empty);
begin
if Ada.Command_Line.Argument_Count = 0 then
Put_Line ("Usage: prog <file1> <file2> ...");
Put_Line ("Merge the sorted files file1, file2...");
return;
end if;
for I in Streams'Range loop
Open (Streams (I).File, In_File, Ada.Command_Line.Argument (I));
Fetch (Streams (I));
end loop;
while More_Data loop
declare
Stream : Stream_Type renames Streams (Next_Stream);
begin
Put_Line (Stream.Value.Element);
Fetch (Stream);
end;
end loop;
end Stream_Merge;

View file

@ -0,0 +1,89 @@
// ------------------------------------------------------------
// Helper that prints a number followed by a space (like C++ `display`)
function display(num) {
process.stdout.write(num + ' ');
}
// ------------------------------------------------------------
// merge2 merge two sorted collections and call `action` for each
// element in sorted order.
function merge2(c1, c2, action) {
let i1 = 0; // index into c1
let i2 = 0; // index into c2
while (i1 < c1.length && i2 < c2.length) {
if (c1[i1] <= c2[i2]) {
action(c1[i1++]);
} else {
action(c2[i2++]);
}
}
// copy the rest of c1 (if any)
while (i1 < c1.length) {
action(c1[i1++]);
}
// copy the rest of c2 (if any)
while (i2 < c2.length) {
action(c2[i2++]);
}
}
// ------------------------------------------------------------
// mergeN merge **any number** of sorted collections.
// `all` is an iterable (e.g. an array) that contains the
// collections to be merged. `action` is called for each value
// in global sorted order.
function mergeN(action, all) {
// Create a list of “ranges”: each entry keeps the source array
// and the current index inside that array.
const ranges = Array.from(all, col => ({
arr: col,
pos: 0, // points to the next element to read
end: col.length
}));
let done = false;
while (!done) {
done = true;
let least = null; // reference to the range that currently has the smallest element
// Scan every range looking for the smallest next element.
for (const r of ranges) {
// skip exhausted ranges
if (r.pos >= r.end) continue;
if (least === null || r.arr[r.pos] < least.arr[least.pos]) {
least = r;
}
}
// If we found a nonempty range, emit its element and advance it.
if (least !== null) {
done = false;
action(least.arr[least.pos]);
++least.pos;
}
}
}
// ------------------------------------------------------------
// Demo the same tests that the C++ `main` performed
(function main() {
const v1 = [0, 3, 6];
const v2 = [1, 4, 7];
const v3 = [2, 5, 8];
// merge2(v2, v1, display);
merge2(v2, v1, display);
console.log(); // newline
// mergeN(display, { v1 });
mergeN(display, [v1]);
console.log();
// mergeN(display, { v3, v2, v1 });
mergeN(display, [v3, v2, v1]);
console.log();
})();

View file

@ -0,0 +1,94 @@
const std = @import("std");
const print = std.debug.print;
const Order = std.math.Order;
// Generic merge function for two sorted slices
fn merge2(comptime T: type, c1: []const T, c2: []const T, action: *const fn (T) void) void {
var idx1: usize = 0;
var idx2: usize = 0;
while (idx1 < c1.len and idx2 < c2.len) {
if (std.math.order(c1[idx1], c2[idx2]) != .gt) {
action(c1[idx1]);
idx1 += 1;
} else {
action(c2[idx2]);
idx2 += 1;
}
}
while (idx1 < c1.len) {
action(c1[idx1]);
idx1 += 1;
}
while (idx2 < c2.len) {
action(c2[idx2]);
idx2 += 1;
}
}
// Generic merge function for n sorted slices
fn mergeN(comptime T: type, action: *const fn (T) void, all: []const []const T, allocator: std.mem.Allocator) !void {
// Create iterator tracking (current_index, end_index) for each slice
var vit = try allocator.alloc(struct { start: usize, end: usize }, all.len);
defer allocator.free(vit);
// Initialize iterators
for (all, 0..) |slice, i| {
vit[i] = .{ .start = 0, .end = slice.len };
}
while (true) {
var done = true;
var least: ?usize = null;
// Find the slice with the smallest current element
for (vit, 0..) |*iter, i| {
if (iter.start < iter.end) {
if (least == null) {
least = i;
} else if (least) |l| {
if (std.math.order(all[i][iter.start], all[l][vit[l].start]) == .lt) {
least = i;
}
}
}
}
if (least) |l| {
if (vit[l].start < vit[l].end) {
done = false;
action(all[l][vit[l].start]);
vit[l].start += 1;
}
}
if (done) {
break;
}
}
}
fn display(num: i32) void {
print("{d} ", .{num});
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const v1 = [_]i32{ 0, 3, 6 };
const v2 = [_]i32{ 1, 4, 7 };
const v3 = [_]i32{ 2, 5, 8 };
merge2(i32, &v2, &v1, display);
print("\n" , .{});
try mergeN(i32, display, &[_][]const i32{&v1}, allocator);
print("\n" , .{});
try mergeN(i32, display, &[_][]const i32{ &v3, &v2, &v1 }, allocator);
print("\n" , .{});
}