Re: Best way to learn 2d games with D?

2020-03-15 Thread dwdv via Digitalmars-d-learn

On 2020-03-15 18:58, Steven Schveighoffer via Digitalmars-d-learn wrote:

I'd prefer to do it with D.


How about raylib in conjunction with thin d bindings? I prefer it over sdl, 
sfml and the like.

https://www.raylib.com/examples.html (make sure to enable js for embedded 
examples)
https://code.dlang.org/packages/raylib-d
https://github.com/raysan5/raylib/blob/master/BINDINGS.md

Should I just start with another language and then migrate to D later? 


If you can stomach lua(jit), check out love2d. Docs and provided game tutorials are super easy to 
follow:


https://love2d.org/
https://love2d.org/wiki/Category:Tutorials

Lastly, if you're more interested in the gamedev aspect, there's also the option to pick your poison 
from this curated mixed list of slim and fat 2d game engines:


https://thomasgervraud.com/best-2d-game-engine/


Re: wordladder - code improvement

2020-01-31 Thread dwdv via Digitalmars-d-learn

On 2020-01-31 09:44, mark via Digitalmars-d-learn wrote:

I can't use the levenshtien distance because although it is a better solution, 
[...]


Nah, it isn't, sorry for the noise, should have slept before sending the message, was thinking of 
hamming distance:


auto a = "abcd";
auto b = "bcda";

auto hammingDistance(string a, string b) {
return zip(a, b).count!(t => t[0] != t[1]);
}

levenshteinDistance(a, b).writeln; // => 2
hammingDistance(a, b).writeln; // => 4


main() [...] doesn't match the behaviour


There's also std.range.tee if you ever need to perform additional side-effects in a range pipeline, 
which restores the original dot printing:


write("Try ");
auto res = generate!(() => genLadder(words.dup, STEPS))
.enumerate(1)
.tee!(_ => write('.'), No.pipeOnPop) // No.pipeOnPop ensures we're not one 
dot short
.find!(a => !a[1].empty)
.front;
writeln(" ", res[0]);


genLadder() [...] is so compact.


Thinking about it, you could even eliminate the prev variable all together when using ladder.back in 
compWords.


Regarding const correctness, this article and thread might contain useful information: 
https://forum.dlang.org/thread/2735451.YHZktzbKJo@lyonel


By the way, keep the documentation improvements coming, much appreciated!



Re: wordladder - code improvement

2020-01-30 Thread dwdv via Digitalmars-d-learn
From one noob to another: Not much of a difference, but levenshteinDistance seems to be a good fit 
here. About as fast as your solution, slightly lower memory usage. byCodeUnit/byChar might shave off 
a few more ms.


For small scripts like these I'm usually not even bothering with const correctness and selective 
imports. There's also import std; but that might lead to ambiguous imports.


---

import std.algorithm, std.array, std.conv, std.datetime.stopwatch,
   std.functional, std.random, std.range, std.stdio, std.uni;

enum WORDFILE = "/usr/share/hunspell/en_GB.dic";
enum WORDSIZE = 4;
enum STEPS = WORDSIZE;

// could be verified at compile-time
static assert(WORDSIZE % 2 == 0, "WORDSIZE should be even");

alias WordList = string[];
alias WordSet = bool[string];

void main() {
auto sw = StopWatch(AutoStart.yes);
auto words = getWords(WORDFILE, WORDSIZE);
// would be slicker with proper destructuring support
auto res = generate!(() => genLadder(words.dup, STEPS))
.enumerate(1)
.find!(a => !a[1].empty)
.front;
writeln("tries: ", res[0]);
res[1].each!writeln;
writeln(sw.peek); // or sw.peek.total!"msecs"
}

WordSet getWords(string filename, uint wordsize) {
return File(filename).byLine
.map!(line => line.until!(not!isAlpha))
.filter!(word => word.count == wordsize)
.map!(word => word.to!string.toUpper)
.assocArray(true.repeat);
}

WordList genLadder(WordSet words, uint steps) {
WordList ladder;

string update(WordList comps) {
ladder ~= comps.choice;
words.remove(ladder.back);
return ladder.back;
}
WordList compWords(string prev) {
return words.byKey.filter!(word => levenshteinDistance(word, prev) == 
1).array;
}

auto prev = update(words.byKey.array);
foreach (comps; generate!(() => compWords(prev)).take(steps + 1)) {
if (comps.empty) return comps;
prev = update(comps);
}

if (levenshteinDistance(ladder.front, ladder.back) < WORDSIZE)
return [];
return ladder;
}


Re: Reading a file of words line by line

2020-01-16 Thread dwdv via Digitalmars-d-learn

On 2020-01-16 04:54, Jesse Phillips via Digitalmars-d-learn wrote:

[...]
.map!(word => word.to!string.toUpper)
.array
.sort
.uniq
.map!(x => tuple (x, 0))
.assocArray ;



.each!(word => words[word.to!string.toUpper] = 0);

isn't far off, but could also be (sans imports):

return File(filename).byLine
.map!(line => line.until!(not!isAlpha))
.filter!(word => word.count == wordsize)
.map!(word => word.to!string.toUpper)
.assocArray(0.repeat);


Re: Reading a file of words line by line

2020-01-15 Thread dwdv via Digitalmars-d-learn

On 2020-01-15 16:34, mark via Digitalmars-d-learn wrote:

Is this as compact as it _reasonably_ can be?


How about this?

auto uniqueWords(string filename, uint wordsize) {
import std.algorithm, std.array, std.conv, std.functional, std.uni;

return File(filename).byLine
.map!(line => line.until!(not!isAlpha))
.filter!(word => word.count == wordsize)
.map!(word => word.to!string.toUpper)
.array
.sort
.uniq;
}


Re: Using tasks without GC?

2020-01-04 Thread dwdv via Digitalmars-d-learn

Creates a Task on the GC heap that calls an alias.


If possible, there's also scopedTask, which allocates on the stack: 
https://dlang.org/phobos/std_parallelism.html#.scopedTask


So my question is: Has anyone done any analysis over how "dangerous" it is to use GC'd tasks for 
_small_ tasks (in terms of milliseconds)?


Nothing major, but https://github.com/mratsim/weave/tree/master/benchmarks/fibonacci puts quite a 
bit of pressure on various implementations. You might want to profile ./pfib 40:


import std;

ulong fib(uint n) {
if (n < 2) return n;

auto x = scopedTask!fib(n-1); // vs. Task!fib(n-1);
taskPool.put(x);
auto y = fib(n-2);
return x.yieldForce + y; // {yield,spin,work}Force
}

void main(string[] args) {
enforce(args.length == 2, "Usage: fib ");
auto n = args[1].to!uint;
// defaultPoolThreads(totalCPUs);
writefln!"fib(%d) = %d"(n, fib(n));
}

At least D isn't locking up beyond 12 tasks; looking at you, stdlib-nim. :)


Re: Finding Max Value of Column in Multi-Dimesional Array

2019-07-05 Thread dwdv via Digitalmars-d-learn

On 7/5/19 9:56 PM, ag0aep6g via Digitalmars-d-learn wrote:

On 05.07.19 20:49, Samir wrote:
As a follow-on to my earlier question, is there a way to pass a 
variable to the `map` function that specifies the column, rather than 
hard-coding it?  I'm thinking of something like:


p.map!("a[column]").maxElement.writeln;


You can't do that with the string style, because the string is turned 
into a function inside of `map`. Your `column` isn't visible there.


It works when you pass an actual callable instead, e.g. a lambda:

p.map!(a => a[column]).maxElement.writeln;


Furthermore, Samir, the parameter `a` can be renamed to whatever you 
prefer or what fits the code at hand best, e.g. `(row => row[column])`, 
as opposed to the string version, where only a small set of mostly 
single character names is supported.


Re: Finding Max Value of Column in Multi-Dimesional Array

2019-07-05 Thread dwdv via Digitalmars-d-learn

On 7/5/19 9:56 PM, ag0aep6g via Digitalmars-d-learn wrote:

On 05.07.19 20:49, Samir wrote:
As a follow-on to my earlier question, is there a way to pass a 
variable to the `map` function that specifies the column, rather than 
hard-coding it?  I'm thinking of something like:


p.map!("a[column]").maxElement.writeln;


You can't do that with the string style, because the string is turned 
into a function inside of `map`. Your `column` isn't visible there.


It works when you pass an actual callable instead, e.g. a lambda:

p.map!(a => a[column]).maxElement.writeln;


Furthermore, Samir, the parameter `a` can be renamed to whatever you 
prefer or what fits the code at hand best, e.g. `(row => row[column])`, 
as opposed to the string version, where only a small set of mostly 
single character names is supported.


Re: Help with Regular Expressions (std.regex)

2019-03-04 Thread dwdv via Digitalmars-d-learn

On 3/3/19 7:07 PM, Samir via Digitalmars-d-learn wrote:
I am belatedly working my way through the 2018 edition of the Advent of 
Code[1] programming challenges using D and am stumped on Problem 3[2].  
The challenge requires you to parse a set of lines in the format:

#99 @ 652,39: 24x23
#100 @ 61,13: 15x24
#101 @ 31,646: 16x28

I would like to store each number (match) as an element in an array so 
that I can refer to them by index.


There is also std.file.slurp which makes this quite easy:
slurp!(int, int, int, int, int)("03.input", "#%d @ %d,%d: %dx%d");

You can then later expand the matches in a loop and process the claims:
foreach(id, offX, offY, width, height; ...


Re: d word counting approach performs well but has higher mem usage

2018-11-04 Thread dwdv via Digitalmars-d-learn

Assoc array allocations?


Yup. AAs do keep their memory around (supposedly for reuse). [...] 
Why it consumes so much is a question to the implementation.

[...] I guess built-in AAs just love to hoard.


What a darn shame. This way I'm missing out on all those slick internet 
benchmark points. :)


Guess I have to find a workaround then, since it's swapping memory like 
crazy on larger real-world inputs on my fairly low-end machine.



What did I do wrong?


Well, you didn't actually put the keys into the AA ;) I'm guessing you 
didn't look closely at the output, otherwise you would've noticed that 
something was wrong.

[...]
```
Error: associative arrays can only be assigned values with immutable 
keys, not char[]

```
[...]
But when you iterate later, pretty much every key is in fact a reference 
to some older memory, which is still somewhere on the GC heap; you don't 
get a segfault, but neither do you get correct "words".




You are absolutely right, I dismissed the aforementioned error without a 
second thought as soon as the compiler stopped complaining by throwing a 
const declaration at it. Oh well, should have read the assoc array spec 
page more thoroughly since it contains this very snippet here:


```
auto word = line[wordStart .. wordEnd];
++dictionary[word.idup];   // increment count for word
```

And yes, using more irregular log files as input instead of the 
concatenated uniform dict reveals quite a bit of nonsense that is being 
printed to stdout.


Thank you, Stanislav, for taking the time to explain all this.


d word counting approach performs well but has higher mem usage

2018-11-03 Thread dwdv via Digitalmars-d-learn

Hi there,

the task is simple: count word occurrences from stdin (around 150mb in 
this case) and print sorted results to stdout in a somewhat idiomatic 
fashion.


Now, d is quite elegant while maintaining high performance compared to 
both c and c++, but I, as a complete beginner, can't identify where the 
10x memory usage (~300mb, see results below) is coming from.


Unicode overhead? Internal buffer? Is something slurping the whole file? 
Assoc array allocations? Couldn't find huge allocs with dmd -vgc and 
-profile=gc either. What did I do wrong?


```d ===
void main()
{
import std.stdio, std.algorithm, std.range;

int[string] count;
foreach(const word; stdin.byLine.map!splitter.joiner) {
++count[word];
}

//or even:
//foreach(line; stdin.byLine) {
//foreach(const word; line.splitter) {
//++count[word];
//}
//}

count.byKeyValue
.array
.sort!((a, b) => a.value > b.value)
.each!(a => writefln("%d %s", a.value, a.key));
}
```

```c++ (for reference) =
#include 
#include 
#include 
#include 

using namespace std;

int main() {
string s;
unordered_map count;
std::ios::sync_with_stdio(false);
while (cin >> s) {
count[s]++;
}

vector> temp {begin(count), end(count)};
sort(begin(temp), end(temp),
[](const auto& a, const auto& b) {return b.second < a.second;});
for (const auto& elem : temp) {
cout << elem.second << " " << elem.first << '\n';
}
}
```

Results on an old celeron dual core (wall clock and res mem):
0:08.78, 313732 kb <= d dmd
0:08.25, 318084 kb <= d ldc
0:08.38, 38512 kb  <= c++ idiomatic (above)
0:07.76, 30276 kb  <= c++ boost
0:08.42, 26756 kb  <= c verbose, hand-rolled hashtable

Mem and time measured like so:
/usr/bin/time -v $cmd < input >/dev/null

Input words file creation (around 300k * 50 words):
tr '\n' ' ' < /usr/share/dict/$lang > joined
for i in {1..50}; do cat joined >> input; done

word count sample output:
[... snip ...]
50 ironsmith
50 gloried
50 quindecagon
50 directory's
50 hydrobiological

Compilation flags:
dmd -O -release -mcpu=native -ofwc-d-dmd wc.d
ldc2 -O3 -release -flto=full -mcpu=native -ofwc-d-ldc wc.d
clang -std=c11 -O3 -march=native -flto -o wp-c-clang wp.c
clang++ -std=c++17 -O3 -march=native -flto -o wp-cpp-clang wp-boost.cpp

Versions:
dmd: v2.082.1
ldc: 1.12.0 (based on DMD v2.082.1 and LLVM 6.0.1)
llvm/clang: 6.0.1