Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
72
Task/Stream-merge/Ada/stream-merge.adb
Normal file
72
Task/Stream-merge/Ada/stream-merge.adb
Normal 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;
|
||||
89
Task/Stream-merge/JavaScript/stream-merge.js
Normal file
89
Task/Stream-merge/JavaScript/stream-merge.js
Normal 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 non‑empty 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();
|
||||
})();
|
||||
94
Task/Stream-merge/Zig/stream-merge.zig
Normal file
94
Task/Stream-merge/Zig/stream-merge.zig
Normal 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" , .{});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue