dlang Buridan's

This commit is contained in:
Francesco Mecca 2018-02-24 05:30:45 +01:00
parent b2a230933e
commit 508ca5c0a9

100
asino.d
View file

@ -1,12 +1,5 @@
/** /**
Buridan's Donkey, Asino. Buridan's Donkey, Asino.
...a man, being just as hungry as thirsty,
and placed in between food and drink,
must necessarily remain where he is and starve to death.
- Aristole
Copyright: Francesco Mecca Copyright: Francesco Mecca
License: GPLv3 License: GPLv3
Author: Francesco Mecca Author: Francesco Mecca
@ -18,35 +11,67 @@ import std.random;
import std.getopt; import std.getopt;
import std.file; import std.file;
import std.conv; import std.conv;
import std.array;
import std.algorithm;
extern(C)
{
struct pollfd { int fd; short events; short revents; }
int poll(pollfd *fds, int nfds, int timeout);
}
string versionSt = "...a man, being just as hungry as thirsty,
and placed in between food and drink,
must necessarily remain where he is and starve to death.
Aristole";
void void
main (string[] args) main (string[] args)
{ {
bool num = false; bool num, v;
string engine = "mt"; string engine = "mt";
string div;
auto cliOpts = getopt( auto cliOpts = getopt(
args, args,
"numbers|n", "enable number output on screen", &num, "numbers|n", "enable number output on screen", &num,
"divider|d", "divide the arguments using a different divider", &div,
"version|v", "show version and exit", &v,
"engine|e", "Choose the RNG between \"mt\" (Mersenne-Twister, default), \"x\" (xorshift), "engine|e", "Choose the RNG between \"mt\" (Mersenne-Twister, default), \"x\" (xorshift),
\"dr\" (/dev/random), \"du\" (/dev/urandom)", &engine \"dr\" (/dev/random), \"du\" (/dev/urandom)", &engine
); );
if (cliOpts.helpWanted){ if(cliOpts.helpWanted){
defaultGetoptPrinter("Buridan's Donkey", cliOpts.options); defaultGetoptPrinter("Buridan's Donkey\nSort a list of strings randomly", cliOpts.options);
return; return;
} else if(v){
writeln(versionSt);
} }
args = args[1 .. $]; // remove program name string[] toProcess = void;
args.shuffle(engine); if(isaTTY()){
//writeln(typeid(gen)); // read stdin, ignore cli args
toProcess = to!(string[])(stdin.byLine().array());
} else {
toProcess = args[1 .. $]; // remove program name
}
foreach (i, arg; args) { auto res = toProcess.divide(div).shuffle(engine);
foreach (i, arg; res) {
if (!num) writeln(arg); if (!num) writeln(arg);
else writefln("%s: %s", i, arg); else writefln("%s: %s", i, arg);
} }
} }
void shuffle(ref string[] args, string t) string[] divide(string[] args, string div)
{
if (div == "") return args;
else return to!(string[])(args.join.splitter(div).array);
}
string[] shuffle(string[] args, string t)
{ {
if(t == "mt"){ if(t == "mt"){
Mt19937 gen; Mt19937 gen;
@ -65,6 +90,7 @@ void shuffle(ref string[] args, string t)
} else { } else {
throw new Exception("Wrong arguments"); throw new Exception("Wrong arguments");
} }
return args;
} }
@ -84,38 +110,24 @@ template DevRandomGen(string gen)
enum UIntType max = ubyte.max; enum UIntType max = ubyte.max;
string src = gen; string src = gen;
/**
* Unused for /dev/random
*/
void seed(UIntType x0) @safe pure nothrow @nogc {} void seed(UIntType x0) @safe pure nothrow @nogc {}
/**
* Returns the current number in the random sequence.
*/
@property
UIntType front() const// @safe pure nothrow @nogc
{
//auto a = to!UIntType("/dev/random".read(UIntType.sizeof));
//return to!UIntType(a);
return (cast(ubyte[])(src.read(ubyte.sizeof)))[0];
}
/**
* Advances the random sequence.
*/
void popFront() @safe pure nothrow @nogc {} void popFront() @safe pure nothrow @nogc {}
/**
* Captures a range state.
*/
@property @property
typeof(this) save() @safe pure nothrow @nogc UIntType front() const { return (cast(ubyte[])(src.read(ubyte.sizeof)))[0]; }
{
return this; @property
} typeof(this) save() @safe pure nothrow @nogc { return this; }
} }
} }
bool isaTTY()
{
pollfd fds;
int ret;
fds.fd = 0;
fds.events = 0;
ret = poll(&fds, 1, 0);
return ret > 0;
}