Re: length's type.
On Monday, 12 February 2024 at 19:56:09 UTC, H. S. Teoh wrote: But regardless, IMNSHO any programmer worth his wages ought to learn what an unsigned type is and how it works. A person should not be writing code if he can't even be bothered to learn how the machine that's he's programming actually works. I'd like to note that even C++20 onwards has `.ssize`, which is signed size. I do use lengths in arithmetic sometimes, and that leads to silent bugs currently. On the other hand, since going from 16 bits to 32 and then 64, in my user-side programs, I had a flat zero bugs because some length was 2^{31} or greater -- but at the same time not 2^{32} or greater. So, in D, I usually `to!int` or `to!long` them anyway. Or cast in performance-critical places. Another perspective. Imagine a different perfect world, where programmers just had 64-bit integers and 64-bit address space, everywhere, from the start. A clean slate, engineers and programmers designing their first hardware and languages, but with such sizes already feasible. Kinda weird, but bear with me a bit. Now, imagine someone proposing to make sizes unsigned. Wouldn't that be a strange thing to do? The benefit of having a universal arithmetic type for everything, from the ground up -- instead of two competing types producing bugs at glue points -- seems to far outweigh any potential gains. Unsigned integers could have their small place, too, for bit masks and microoptimizations and whatnot, but why sizes? The few applications that really benefit from sizes of [2^{63}..2^{64}) would be the most odd ones, deserving some workarounds. Right now though, we just have to deal with the legacy, in software, hardware, and mind -- and with the fact that quite some environments are not 64-bit. Ivan Kazmenko.
Re: HTTP Post Body Parameters
On Tuesday, 1 August 2023 at 23:57:29 UTC, Vahid wrote: I want to submit a request to server with "x-www-form-urlencoded" header. Isn't https://dlang.org/library/std/net/curl/post.html what you need?
Re: A New Era for the D Community
On Wednesday, 3 May 2023 at 11:13:34 UTC, Mike Parker wrote: ... Our enthusiasm is high, and we're ready to get going. I think you'll like where we're headed. Interesting. Good luck with the endeavor! Ivan Kazmenko.
Re: Breaking ";" rule with lambda functions
On Monday, 1 August 2022 at 20:36:12 UTC, pascal111 wrote: My complaint is about that a function is not a same as an expression that functions return values, but expressions being evaluated to provide values. An analogy. With a ternary expression, we write: `x = (cond ? a : b);` The traditional look of it is: `if (cond) x = a; else x = b;` Note how we have a semicolon after `x = a` in the latter form, but can't have it in the former. Ivan Kazmenko.
vectorization of a simple loop -- not in DMD?
Hi. I'm looking at the compiler output of DMD (-O -release), LDC (-O -release), and GDC (-O3) for a simple array operation: ``` void add1 (int [] a) { foreach (i; 0..a.length) a[i] += 1; } ``` Here are the outputs: https://godbolt.org/z/GcznbjEaf From what I gather at the view linked above, DMD does not use XMM registers for speedup, and does not unroll the loop either. Switching between 32bit and 64bit doesn't help either. However, I recall in the past it was capable of at least some of these optimizations. So, how do I enable them for such a function? Ivan Kazmenko.
Re: Release D 2.100.0
On Sunday, 15 May 2022 at 11:05:38 UTC, Martin Nowak wrote: Glad to announce D 2.100.0, ♥ to the 41 contributors. Congratulations on the milestone number! Ivan Kazmenko.
Re: d strings are the bane of my existance
On Sunday, 5 December 2021 at 16:37:21 UTC, Chris Katko wrote: Yes! Thank you! I just realized the latter part was broken when I switched to using a uint for the addr. But I didn't know string is an alias for immutable(char)[]! Thank you! Yeah, a `const(char)[]` argument is designed to accept both `immutable(char)[]` (strings) and just `char[]` (mutable arrays of chars) for the arguments. Ivan Kazmenko.
Re: Release Candidate 2.097.0 [was: Re: Beta 2.097.0]
On Saturday, 29 May 2021 at 11:00:50 UTC, Martin Nowak wrote: On Thursday, 13 May 2021 at 13:29:55 UTC, Martin Nowak wrote: Glad to announce the first beta for the 2.097.0 release, ♥ to the 54 contributors. http://dlang.org/download.html#dmd_beta http://dlang.org/changelog/2.097.0.html Release Candidate is live now. Some of the changelog entries look sweet!
Re: Map of functions
On Friday, 14 December 2018 at 15:38:49 UTC, Giovanni Di Maria wrote: Hi Is there an utility to print the functions in a source file, for example: - main() --- calculate() - print() --- simulate() - print() . Thank you very much Giovanni Di Maria Do you really have a nested function print() inside a nested function calculate() inside main()? That is, void main() { void calculate() { void print() { } // maybe some calls to print() } // maybe some calls to calculate() } Or are you talking about the sequence in which function are *called*, and from where? Please clarify. Ivan Kazmenko.
Re: dmd64 on Windows: how?
On Sunday, 12 August 2018 at 03:49:04 UTC, Mike Parker wrote: On Saturday, 11 August 2018 at 19:50:30 UTC, Ivan Kazmenko wrote: I've installed the components shown in wiki image: v141 tools and the SDKs. VS 2017 Community includes everything you need. There's no reason to install the SDK separately. If it's installed first, the DMD installer will find it. The latest version will install the MinGW system libs and the lld linker if no VS installation is found. And for the past few versions, when you run dmd it will look for the VS installation as needed. So it should work out of the box without the need for the separate SDK or mucking about with the paths in sc.ini. Is your VS 2017 the Community edition? Yeah, I have VS 2017 Community Edition, and I was struggling trying to make 64-bit linking work, both with .7z archive and with .exe installer. The .exe installer dmd-2.081.1.exe I've just tried again. With default settings, it just installs into C:\D\ . Its sc.ini is almost empty, no sign of Visual Studio environment variables or paths. Then I run cmd.exe: ~ Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. C:\D>dmd2vars64.bat Setting up 64-bit environment for using DMD 2 from C:\D\dmd2\windows\bin. dmd must still be called with -m64 in order to generate 64-bit code. This command prompt adds the path of extra 64-bit DLLs so generated programs which use the extra DLLs (notably libcurl) can be executed. C:\D>echo void main () {} > a.d C:\D>dmd -m64 a.d C:\D\dmd2\windows\bin\lld-link.exe: error: could not open libcmt.lib: no such fi le or directory Error: linker exited with status 1 ~ My Windows version is Windows Server 2008 R2. Microsoft Visual Studio Community 2017, version 15.7.6. At C:\Program Files (x86), there are: Microsoft Visual Studio[ 2754M ] Microsoft Visual Studio 12.0 [ 50M ] Microsoft Visual Studio 14.0 [ 954M ] The latter two contain some remains of the previous installations, so that may be the issue with detecting the current Visual Studio version. Ivan Kazmenko.
Re: dmd64 on Windows: how?
Well, I tried all your suggestions. (Actually re-tried a few times.) Thanks, Laurent and Kagamin! On Friday, 10 August 2018 at 14:47:04 UTC, Laurent Tréguier wrote: Did you have a look at the wiki ? It looks like the image shows what needs to be installed: https://wiki.dlang.org/Installing_DMD#Installing_the_Microsoft_toolchain This was most close to solving my problem. Thanks! I've installed the components shown in wiki image: v141 tools and the SDKs. The sc.ini information in the wiki looks outdated. At least the sc.ini from the .7z archive is much cleaner than it used to be. The whole 64-bit section looks like this: ~ [Environment64] LIB=%@P%\..\lib64 ; needed to avoid COMDAT folding (bugzilla 10664) DFLAGS=%DFLAGS% -L/OPT:NOICF ~ So I proceeded with the wiki instructions: to find and run a 64-bit Visual Studio command prompt, to ask the environment variables from there. And Visual Studio 2017 brings new tricky paths to handle. Here is how my sc.ini 64-bit section looks now, when everything seems to work: ~ [Environment64] LIB=%@P%\..\lib64 ; needed to avoid COMDAT folding (bugzilla 10664) DFLAGS=%DFLAGS% -L/OPT:NOICF ; here are the actual paths VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\ WindowsSdkDir=C:\Program Files (x86)\Windows Kits\10\ UniversalCRTSdkDir=C:\Program Files (x86)\Windows Kits\10\ UCRTVersion=10.0.17134.0 ; here is the actual version LINKCMD=%VCINSTALLDIR%\Tools\MSVC\14.14.26428\bin\HostX64\x64\link.exe ; needed with /DEBUG to find mspdb*.dll (only for VS2012 or later) PATH=%PATH%;%VCINSTALLDIR%\bin\HostX64\x64 ~ Specifically, LINKCMD part deviates from the instructions. The linker is now buried deeper into \Tools\MSVC\14.14.26428\bin\HostX64\x64\. Yep, that contains a version number too, which may change with each update. Meanwhile, the tutorial suggests just the following: LINKCMD=%VCINSTALLDIR%\bin\x86_amd64\link.exe Anyway, now 64-bit linking seems to be working, so I'll stop digging. Ivan Kazmenko.
dmd64 on Windows: how?
Hi, How should I set up DMD to be able to `dmd -m64` on Windows nowadays? I usually download the 7z, but it broke when I replaced my Visual Studio with 2017 edition. Now, I tried the current 2.081.1 .exe installer. It didn't propose any additional 64-bit related options. After the installation, `dmd -m64` complains that the linker could not find `libcmt.lib`. The previous time I tried finding the right `libcmt` and treating the subsequent errors, I failed to locate all the correct libraries in Microsoft's Visual Studio and SDKs. This time, I'd rather follow some up-to-date guide than waste the time again. So, what's the most current guide to make 64-bit linking work on Windows? I'm fine with having to install more LLVM or MinGW or Microsoft stuff, I just don't seem to know what I need. Ivan Kazmenko.
Re: On D in competitive programming
On Tuesday, 31 July 2018 at 00:52:22 UTC, 9il wrote: Are competitors allowed to use mir-algorithm and mir-random? The libraries can be used for graphs (Tarjan algorithm), matrices/tensors, nd-iteration, RNGs, interpolation, and distributions? Sadly, no: most of the time, language compilers on the server side are provided as they are out-of-the-box. I'll try to explain why. When a language is added to a competition, one of the goals for the organizers is to keep the whole thing fair. Different languages have different pros and cons already as they are, and what is an implementation-heavy problem for one language is solved in a couple lines with another. So, the availability of several programming languages already puts some burden on the problemsetters: at least for important competitions, they have to come up with problems which don't play too much into the strengths of any particular language, and that means knowing what to generally expect of all the languages. For example, most problems don't rely on number crunching with integers above 64 bits, since C++ is notoriously lacking in this regard. This all gets a new dimension if a platform decides to supply additional libraries. Once it's done for one language, there are no clear boundaries: if we get mir-algorithm for D, we will have to at least install Boost for C++, and numpy for Python, and the users of other languages also ask for their favourite libraries, which are in turn more powerful than Boost, and so on. And it would take significant expertise to balance such requests so that no language has too much of an unfair advantage or disadvantage. It takes a bit of expertise too to keep the libraries in all languages working and up-to-date. All the way, the problemsetters now have to avoid a different set of topics, changing with new libraries being added. Yet another factor is that there are central competitions perceived as the most important, which are currently ACM ICPC World Finals for university teams, and their regional contests. Many platforms strive to act as training grounds for the important competitions. So when the World Finals, which are understandably conservative, don't do X, it's a disincentive to do X for the training grounds too. So, the default approach is to keep each language at a bare minimum. It would be nice to have this feature, as mir-algorithm can be a good default library for competitive programming. Plus competitors can add additional graph algorithms. It may still be reasonable to ask for additional libraries on the platforms where the focus is not some big competition: e.g., perhaps no for ACM ICPC archives, perhaps yes for interview training sites. For a particular platform and a particular cause (e.g., a training course for a learning platform), it's entirely possible to have D with mir-algorithm installed on the platform. Ivan Kazmenko.
Re: On D in competitive programming
On Monday, 30 July 2018 at 19:44:32 UTC, Steven Schveighoffer wrote: a lifetime ago, I competed using topcoder (and wrote a bunch of problem sets for them too). Topcoder had a "challenge" phase, where you could challenge the solutions of others. Nice! I just found your profile and problem sets from 2003-2004. I started using TopCoder in 2005, didn't see these earlier. Is there anything like that in codeforces, and if so, is D an advantage as a "somewhat obscure" language (i.e. competitors can't always understand your code)? Yeah, in a way. The challenges are called "hacks", and can happen for the whole duration of the contest. But to hack solutions for a problem, you have to first write your own solution to this problem, pass preliminary tests with it, and lock it so you can't resubmit. The key difference is, when the hacked solution itself was not locked, it still can be fixed and resubmitted (with a score penalty), which is actually a win-win. As for how a different language helps, well, perhaps it does. But, sadly, competitive programming style often goes against readability, to the extent the language allows it. In that regard, somewhat unexpectedly, I find other languages (e.g., Java or Python) more readable than C++ despite the fact that I'm less experienced with them. In C++, most competitive programming code contains a bunch of the author's exclusive #defines for the language shortcomings (or worse, #defines just to save typing). And since #defines are so flexible, everyone has their own version of the language, and some of the resulting code is straight unreadable without a deciphering effort. Ivan Kazmenko.
Re: On D in competitive programming
On Sunday, 29 July 2018 at 07:51:00 UTC, Jim Balter wrote: Actually, map!something does not drop empty parentheses, so mentioning that does not help. Parentheses containing 0 or 1 arguments can be omitted ... and you omit them for 1 argument in 3 places, and no instances of omitted empty parentheses. And I think it would be less confusing to an unfamiliar reader to mention UFCS, because the chained calls don't fit the function !(args1) (args2) syntax that you mention. While that's technically right, I'd like to skip further explanations of the syntax. The same as I skipped why the problem is solved by such code at all (and it's even less obvious). In both cases, careful explanations would require a good paragraph or two, but are beside the point. The point of the article is more to just show how it feels and to spark interest than to explain everything. On the other hand, if I had to write a guide for competitive programmers on how to use D, such things sure would be included. Ivan Kazmenko.
Re: On D in competitive programming
Thanks for the feedback! On Saturday, 28 July 2018 at 20:33:14 UTC, Cym13 wrote: 1. Your real name isn't written in the article so the link "with some successes" won't tell much to someone that doesn't already know you Hmm, didn't think of it. I phrased it differently now. In my experience, the participants' nicknames in competitive programming are mostly tightly coupled with real names, and otherwise, the blog author's profile is one familiar click away. So for a local Codeforces reader, that hopefully wasn't a problem anyway. 2. When you briefly explain templates I think it's important to mention that empty parentheses may be omitted to allow the reader to make the link between function!(arg1)(arg2) and map!something. Explaining UFCS isn't necessary there though I think since it's obvious that there is some kind of chaining at play (not that you did, just thinking out loud). Yeah, good point, mentioned it now. Also I have a question: I find very nice that some platforms propose D even though not all do, but are they generally keeping it up to date with DMD or stuck at something ancient? It varies depending on the platform. A few examples: codeforces.com just recently upgraded from DMD 2.074 to DMD 2.079 (so I could show the compile-time writefln in the post); atcoder.jp is at DMD 2.070 but also has LDC 0.17.0 and GDC 4.9.4; codechef.com has some ancient GDC, barely usable; hackerearth.com has DMD 2.074.1; csacademy.com (Romanian competitive programming website) does not yet have D, but I hope they add it in a few months; hackerrank.com claims to have DMD 2.079, but recently stopped supporting it in live contests because of a paradigm shift. Namely, they now strive to supply the reading-from-file solution template for each problem, and apparently didn't get to writing it in all 35 languages they generally have. I offered my help, but the support was kind of unresponsive, so seeking another point of contact now. Generally, it seems to correlate with the health of the platform's backend. In my code in competitions, I tend to now use features around 2.070 so that they are mostly supported. Ivan Kazmenko.
On D in competitive programming
Hey, I wrote a post with my general reflections on using D in competitive programming. Mostly compared to C++, since that's what more than 90% of people use for it. The post is tailored to cover only the competitive programming specifics. http://codeforces.com/blog/entry/60890 (en+ru, the language switch is at the top) Ivan Kazmenko.
Re: opCmp / opEquals do not actually support partial orders
On Wednesday, 18 July 2018 at 15:13:24 UTC, rikki cattermole wrote: On 19/07/2018 3:03 AM, Ivan Kazmenko wrote: That's by DMD32 on Windows. (Sorry, my DMD64 broke after upgrading Visual Studio to 2017, and I failed to fix it right now. Anyway, it's not like x86_64 uses a different set of general purpose floating-point hardware, right?) Boy do I ever have some bad news for you! SSE for 64bit and x87 for 32bit, as per run.dlang.org. Wow, thanks! As per https://run.dlang.io/, it's fast for float and double, but slow for reals (which are 80 bits and don't fit into the fancy instructions you mention). Unfortunately, it fails to compile with -m32, but anyway, point taken. As an aside, learning something new after virtually every post is why I love the D forum/newsgroup. Ivan Kazmenko.
Re: opCmp / opEquals do not actually support partial orders
On Wednesday, 18 July 2018 at 14:02:28 UTC, Dominikus Dittes Scherkl wrote: On Wednesday, 18 July 2018 at 13:12:05 UTC, Ivan Kazmenko wrote: Leaving x uninitialized, or using floats, work about the same. No, floats are a whole lot less slow. Are they? Locally, I don't see much difference. Code: - import std.datetime.stopwatch, std.math, std.stdio; immutable float limit = 10 ^^ 7; void main () { int s; auto sw = StopWatch (AutoStart.yes); auto start = sw.peek (); for (float x = NaN (0), i = 0; i < limit; i++) s += (i < x); auto now = sw.peek (); writeln (now - start, ", sum is ", s); } - Result: - 1 sec, 467 ms, 40 μs, and 6 hnsecs, sum is 0 - Fluctuating within a few per cent, but very similar to version with doubles. That's by DMD32 on Windows. (Sorry, my DMD64 broke after upgrading Visual Studio to 2017, and I failed to fix it right now. Anyway, it's not like x86_64 uses a different set of general purpose floating-point hardware, right?) Ivan Kazmenko.
Re: opCmp / opEquals do not actually support partial orders
On Tuesday, 17 July 2018 at 21:18:12 UTC, John Colvin wrote: Just do what std.typecons.Proxy does and return float.nan for the incomparable case. Isn't it slow though on current processors? I just threw together a test program. - import std.datetime.stopwatch, std.math, std.stdio; immutable double limit = 10 ^^ 7; void main () { int s; auto sw = StopWatch (AutoStart.yes); auto start = sw.peek (); for (double x = NaN (0), i = 0; i < limit; i++) s += (i < x); auto now = sw.peek (); writeln (now - start, ", sum is ", s); } - Essentially, it compares a double x (initialized as a quiet NaN with payload 0) to a numeric double i, ten million times. Leaving x uninitialized, or using floats, work about the same. And here is the result: - 1 sec, 593 ms, 116 μs, and 3 hnsecs, sum is 0 - So, for a comparison involving NaN, we can do only a few million of them a second. Granted, my Core i7-2600K is more than 5 years old already, but the situation is unlikely to get any better. But that's still a couple orders of magnitude slower than normal vs. normal floating-point comparison: try assigning some regular number to x, then the test takes ~50ms. As far as I know, rare floating-point operations (such as this, or using subnormal numbers) are, or rather should be, treated as exceptions. The hardware manufacturers neglect such rare operations to fit a bit more efficiency in the more common ones (or they are just lazy). As a result, the developers don't overuse them. Ivan Kazmenko.
Re: dmd optimizer now converted to D!
On Thursday, 5 July 2018 at 14:30:05 UTC, Dukc wrote: foreach(j, ref piece; cast(int[4][]) a) { auto pieceI = j * 4; static foreach(i; 0 .. piece.length) piece[i] = pieceI + i; } Can probably be made even better by designing some template helper. Thanks! The cast to an array of int[4]s is just hilarious.
Re: dmd optimizer now converted to D!
On Thursday, 5 July 2018 at 14:05:42 UTC, Seb wrote: FYI: you can introduce scopes with static foreach to declare new variables: for (int i = 0; i < 4 * n; i += 4) { static foreach (k; 0..4) {{ auto idx = i + k a[idx] += idx; }} } Thanks! The two parentheses trick is nice. Generally, I was reluctant to declare a variable because, well, micro-optimizing means being dissatisfied with compiler optimization. So the mindset didn't allow me to just go and declare a variable in the innermost loop, in fear that the optimizer might not optimize the allocation away.
Re: dmd optimizer now converted to D!
On Wednesday, 4 July 2018 at 17:22:22 UTC, H. S. Teoh wrote: ... dmd *is* capable of things like strength reduction and code lifting, but as Walter himself has said, it does *not* implement loop unrolling. Ow! I always thought it did loop unrolling in some cases, I was just never lucky when I checked. And now you and Walter say its implementation started only recently. Good to know the actual state of things. Manual loop unrolling did help me a couple of times with C++ and D. - By the way, what's a relatively painless way to manually unroll a loop in D? As a simple example, consider: for (int i = 0; i < 4 * n; i++) a[i] += i; With C[++], I did simply like this: for (int j = 0; j < 4 * n; j += 4) { #define doit(i) a[i] += i doit(j + 0); doit(j + 1); doit(j + 2); doit(j + 3); } This looks long, but on the positive side, it does not actually alter the expression: however complex and obscure the "a[i] += i" would be in a real example, it can remain untouched. With D, I used mixins, and they were cumbersome. Now that we have static foreach, it's just this: for (int i = 0; i < 4 * n; i += 4) static foreach (k; 0..4) a[i + k] += i + k; This looks very nice to me, but still not ideal: a static-foreach argument cannot encapsulate a runtime variable, so we have to repeat "i + k" twice. This can get cumbersome for a more complex example. Is there any better way? To prevent introducing bugs when micro-optimizing, I'd like the loop body to remain as unchanged as it can be. Ivan Kazmenko.
Re: how to correctly populate an array of dynamic closures?
On Thursday, 29 March 2018 at 15:38:14 UTC, ag0aep6g wrote: <...> With immutable, this is certainly a problem. https://issues.dlang.org/show_bug.cgi?id=2043 Wow, such history for the bug! Two possible workarounds: int delegate () [] iuns; foreach (i; 0..2) iuns ~= (j) { return () => j; } (i); foreach (i; 0..2) writeln (iuns[i] ()); /* 0 and 1 */ static struct S { int i; int m() { return i; } } int delegate () [] juns; foreach (i; 0..2) juns ~= &(new S(i)).m; foreach (i; 0..2) writeln (juns[i] ()); /* 0 and 1 */ Thank you ag0aep6g and Dennis for showing the possible workarounds! On Thursday, 29 March 2018 at 15:47:33 UTC, Dennis wrote: A delegate is a function with a pointer to the stack frame where it was created. It doesn't copy or insert the value of 'i', it still refers to the very same location in memory as the i from the for-loop. After the for-loop, that value is 1, so all delegates refering to that i return 1. The solution is to generate a new local variable for each closure with a helper function: So, basically, one has to create and call another function, or explicitly copy onto the heap, in order to ensure the copy of the loop variable is stored for the closure. My (mis)understanding was that there's some additional magic happening for closures that get stored on the heap, as opposed to delegates used before their context goes out of scope. As long as the whole story is that simple, fine. Ivan Kazmenko.
how to correctly populate an array of dynamic closures?
Here's a simplified example of what I want to achieve. I first create funs, an array of two delegates. I want funs[0] to always return 0 and funs[1] to always return 1. By assigning the constants directly (see the code below), I achieve exactly that. Now, I want to use a loop to assign the values, and this is where things stop working. My first try is guns, populated with `foreach (i; 0..2) guns ~= () => i;`. But both guns[0] and guns[1] return 1. I tried to circumvent that by populating another array, huns, with functions returning immutable copies of the loop variable, but the effect was the same. import std.stdio; void main () { int delegate () [] funs; funs ~= () => 0; funs ~= () => 1; foreach (i; 0..2) writeln (funs[i] ()); // 0 and 1 as expected int delegate () [] guns; foreach (i; 0..2) guns ~= () => i; foreach (i; 0..2) writeln (guns[i] ()); // 1 and 1, why? int delegate () [] huns; foreach (i; 0..2) { immutable int j = i; huns ~= () => j; } foreach (i; 0..2) writeln (huns[i] ()); // 1 and 1, why? } In my real use case, the delegates actually get stored in different structs or classes instead of a single array, and instead of returning 0 and 1, they call another function with argument 0 and 1, respectively. Also, the number of delegates to create is known only at runtime. However, I believe that won't be a problem once I grasp how to do this basic example. So, why do delegates of guns[] and huns[] all return 1, and how to correctly reproduce the behavior of funs[] while populating it in a loop? Ivan Kazmenko.
Re: Seeking lecturer - D language (Moscow)
On Wednesday, 14 March 2018 at 11:38:20 UTC, Dmitry Olshansky wrote: At the moment it’s a bit early stage but we are looking for enthusiast who has spare time and desire to spread the knowledge of D supremacy among students. The course will replace an equivalent of 1 year C++ course, but may start as half-year proof of concept. Sounds nice! Unfortunately, I won't be able to help in Moscow, but if the idea ever spreads to St. Petersburg, I'd definitely consider that. Which university it is now, by the way? I've been exploring the possibility to use D in teaching at my uni (St. Petersburg State University), but didn't push it much, and got no result so far. Ivan Kazmenko.
Re: An unfortunate quirk of DMD32 converting floating-point to string
On Tuesday, 26 December 2017 at 23:58:43 UTC, Walter Bright wrote: On 12/26/2017 3:41 PM, Ivan Kazmenko wrote: While exploring quirks of floating-point values, as well as C/C++/D convenience with them, I stumbled on, in essence, the following (DMD32 on Windows): The issue is really with the DMC++ C runtime library, as that is what Phobos relies on for floating point formatting. In the issue tracker: https://issues.dlang.org/show_bug.cgi?id=18139
An unfortunate quirk of DMD32 converting floating-point to string
While exploring quirks of floating-point values, as well as C/C++/D convenience with them, I stumbled on, in essence, the following (DMD32 on Windows): void main () { import std.stdio : writefln; double x = 128.0;// same for real or float writefln ("%.20a", x); // 0x1.p+7, right writefln ("%.20f", x); // 127.9000, wrong } 1. The internal representation is fine: the exponent (before shift) is 7, and the mantissa is all-zeroes (except the "1." part which is not stored). 2. Formatting to a decimal representation goes off in a bad way, giving the wrong third significant digit. 3. The trail of 9s is the same ~20 decimal digits for every floating-point type, which suggests that they are all converted to 80-bit real before formatting. This obscures their difference in width, which is bad from at least the learning standpoint. Point 2 is sad. One would expect at least the exact powers of two to be stored exactly. And indeed they are. But trying to demonstrate it gives the wrong impression that they are not. This adds unnecessary confusion to the already complex subject of how floating-point values work, and learning the subject with D becomes much harder. On the competition front, this already seems to be settled: at least with MinGW GCC, both C printf and C++ cout correctly display powers of two - and perhaps any small integers exactly stored as floating-point data, for that matter. With DMD64, the issue vanishes. This strongly suggests that 32-bit druntime is the culprit. And indeed, the Phobos "formatValue ... if (is(FloatingPointTypeOf!T) && ...)" for floating-point calls snprintf from druntime, after which I couldn't easily track it to the source code. Should this be so? And regardless, perhaps snprintf (or Phobos or whatever will do the dirty work) can adapt a more modern approach so that integers in floating-point don't get corrupted when converted to string representation? Perhaps even without sacrificing much speed. The most obvious way seems to just make multiplications by 10, comparisons and subtractions in a loop, and is likely slow but at least correct for integers. I'm going to make this a bugreport, but first wanted to explicitly point at this in the discussion group, since it's quirky, and I may have easily missed something important. Ivan Kazmenko.
Re: run.dlang.io - a modern way to run D code
On Thursday, 14 December 2017 at 01:52:29 UTC, H. S. Teoh wrote: ... This can, of course, be bound to a custom keybinding, then you'll have your one-stop shop for compiling D snippets without ever seeing (much less typing) any temporary filenames. And without needing an internet connection. That sounds powerful! Like you said, instant win.
Re: Russian AI Cup 2017 - D language support
On Friday, 17 November 2017 at 22:54:47 UTC, Steven Schveighoffer wrote: Cool! Is there any history of people using D in the past for this competition? A few people used D each year it had support, to various success. The highest so far, I think, is Vladislav Isenbaev in 2013. He got 11-th place in the finals: http://2013.russianaicup.ru/contest/4/standings
Russian AI Cup 2017 - D language support
Hi! Russian AI Cup (http://russianaicup.ru) is an annual online AI programming competition by Mail.Ru Group. This year, the task is to write a bot which plays a real-time strategy against other programmer's bots. The competition runs from November 13 to December 24, 2017, and the first elimination round starts on November 24. Traditionally, several programming languages are supported by contest authors, and a few other with some help from the community. I added support for D this year (again), the language pack and example bot can be found here: https://github.com/GassaFM/raicup-2017-dlang-cgdk-en So, if you'd like to give it a try: good luck and have fun! Ivan Kazmenko.
Re: Why 2 ^^ 1 ^^ 2 = 2?
On Thursday, 26 October 2017 at 10:02:54 UTC, Kagamin wrote: On Sunday, 22 October 2017 at 22:28:48 UTC, Ivan Kazmenko wrote: Yeah, and a height-3 tower $a^{b^c}$ (TEX notation) Is $a^{b^c}$ the same as ${a^b}^c$ ? They are drawn slightly differently, so I suppose it's ambiguous indeed. Surely not the same. "3 to the power of (3 to the power of 3)" is "3 to the power of 27", or 7,625,597,484,987. "(3 to the power of 3) to the power of 3" is "27 to the power of 3", or 2187. For an argument, the TEX command "^" accepts either a single character or a bracket-enclosed string of arbitrary length. So $3^3^3$ indeed transforms to ${3^3}^3$, but not for some deeper reason this time. Ivan Kazmenko.
Re: Why 2 ^^ 1 ^^ 2 = 2?
On Sunday, 22 October 2017 at 14:44:04 UTC, Timon Gehr wrote: On 22.10.2017 16:20, Ilya Yaroshenko wrote: .. i thought it should be (2 ^^ 1) ^^ 2 = 4 2 ^^ (1 ^^ 2) == 2 It is standard for ^/**/^^ to be right-associative. (This is also the standard convention in mathematics.) Yeah, and a height-3 tower $a^{b^c}$ (TEX notation) actually means "a to the power of (b to the power of c)", not the other way around. Otherwise, it can be written as $a^{b \cdot c}$, which is only a height-2 tower. The convention also makes at least the following sense. An expression like (((a ^^ b) ^^ c) ^^ d) ^^ e already has an almost bracket-free notation as a ^^ (b * c * d * e). So it is useful to have a bracket-free way to write the other-way-associative variant, a ^^ (b ^^ (c ^^ (d ^^ e))). Ivan Kazmenko.
Re: floating point value rounded to 6digits
On Tuesday, 19 September 2017 at 22:44:06 UTC, greatsam4sure wrote: On Tuesday, 19 September 2017 at 21:52:57 UTC, Ivan Kazmenko wrote: On Tuesday, 19 September 2017 at 20:47:02 UTC, greatsam4sure wrote: double value = 20.89766554373733; writeln(value); //Output =20.8977 How do I output the whole value without using writfln,write or format. How do I change this default The default when printing floating-point numbers is to show six most significant digits. You can specify the formatting manually with writefln, for example, writefln ("%.10f", value); will print the value with 10 digits after the decimal point. The writef/writefln function behaves much like printf in C. See here for a reference on format strings: https://dlang.org/library/std/format/formatted_write.html#format-string Ivan Kazmenko. I don't want to use write,writefln or format. I just want to change the default Unlikely to be possible. The built-in data types, such as float or double, by definition should not be customizable to such degree. Anyway, under the hood, write uses format with the default format specifier "%s" for the values it takes. So perhaps I'm not quite getting what exactly are you seeking to avoid. For example, consider a helper function to convert the values, like the following: import std.format, std.stdio; string fmt (double v) {return v.format !("%.10f");} void main () { double x = 1.01; writeln (x.fmt); // 1.01 } Alternatively, you can wrap your floating-point numbers in a thin struct with a custom toString(): import std.format, std.stdio; struct myDouble { double v; alias v this; this (double v_) {v = v_;} string toString () {return v.format !("%.10f");} } void main () { myDouble x = 1.01, y = 2.02, z = x + y; writeln (z); // 3.03 } Ivan Kazmenko.
Re: floating point value rounded to 6digits
On Tuesday, 19 September 2017 at 20:47:02 UTC, greatsam4sure wrote: double value = 20.89766554373733; writeln(value); //Output =20.8977 How do I output the whole value without using writfln,write or format. How do I change this default The default when printing floating-point numbers is to show six most significant digits. You can specify the formatting manually with writefln, for example, writefln ("%.10f", value); will print the value with 10 digits after the decimal point. The writef/writefln function behaves much like printf in C. See here for a reference on format strings: https://dlang.org/library/std/format/formatted_write.html#format-string Ivan Kazmenko.
Re: writeln() sometimes double prints from main() if I run a thread checking for input?
On Thursday, 31 August 2017 at 14:43:39 UTC, Steven Schveighoffer wrote: Just a thought, but the "double printing" could be a misunderstanding. It could be printing Output\nOutput2, but not getting the 2 out there. No no, it's four lines instead of three. If we change the lines to disjoint sets of letters, the problem persists. Note that DMD 32-bit is using DMC libc. It might be that it gets hung up somehow when expecting input, like it locks the console somehow. I would say that byLineCopy puts the thread to sleep waiting for input, and it doesn't get out of that state. So it could be that the bug only appears when it gets to that state at some point in the output. I'd pepper some sleeps around the outputs to see if you can make the context switches more predictable. Inserting different sleeps into the threads makes the problem go away (cannot reproduce). Inserting identical sleeps produces the error with roughly the same probability. Anyway, I've reported it (https://issues.dlang.org/show_bug.cgi?id=17797), along with a more or less exact version (2.073.2) where the problem was introduced. Ivan Kazmenko.
Re: writeln() sometimes double prints from main() if I run a thread checking for input?
On Wednesday, 30 August 2017 at 13:33:06 UTC, Ivan Kazmenko wrote: Interesting. As to what to do with it, no idea for now. At the very least we can issue a bug report, now that at least two people can reproduce it, so it is unlikely to be environment-dependent. Reported: https://issues.dlang.org/show_bug.cgi?id=17797 .
Re: writeln() sometimes double prints from main() if I run a thread checking for input?
On Wednesday, 30 August 2017 at 13:24:55 UTC, Ivan Kazmenko wrote: On Wednesday, 30 August 2017 at 10:55:20 UTC, Timothy Foster wrote: import std.stdio, core.thread; void main(){ auto thread = new Thread().start; writeln("Output"); writeln("Output2"); writeln("Output3"); while(true){} } void func(){ foreach(line; stdin.byLineCopy){} } I also cannot reproduce this. My current system is Win7 64-bit. I tried 32-bit dmd 2.072.0 and 2.075.1, with optimizations turned on and off, but it prints correctly tens of times in each case. Try running the program in a bare console (cmd.exe on Windows, or some *sh on Linux). If the problem goes away, your usual environment is likely at fault. If not,.. well, no idea for now. Hey, I followed my own advice and do see the same issue! when: 1. compiling with dmd 2.075.1 (optimization switches seem to be irrelevant but the issue does not reproduce with 2.072.0), 2. running in a bare cmd.exe, and 3. running the program as just "a.exe", so that it waits for console input (previously I redirected some input to it, like "a.exe
Re: writeln() sometimes double prints from main() if I run a thread checking for input?
On Wednesday, 30 August 2017 at 10:55:20 UTC, Timothy Foster wrote: import std.stdio, core.thread; void main(){ auto thread = new Thread().start; writeln("Output"); writeln("Output2"); writeln("Output3"); while(true){} } void func(){ foreach(line; stdin.byLineCopy){} } I also cannot reproduce this. My current system is Win7 64-bit. I tried 32-bit dmd 2.072.0 and 2.075.1, with optimizations turned on and off, but it prints correctly tens of times in each case. Try running the program in a bare console (cmd.exe on Windows, or some *sh on Linux). If the problem goes away, your usual environment is likely at fault. If not,.. well, no idea for now. Ivan Kazmenko.
Re: writeln() sometimes double prints from main() if I run a thread checking for input?
On Wednesday, 30 August 2017 at 10:13:57 UTC, Timothy Foster wrote: I'm not sure if this is a known issue, or if I just don't understand how to use threads, but I've got writeln statements sometimes printing out twice in some areas of my code. <...> Does anyone know what is causing this or how I can fix it? Difficult to say by what you posted. You may want to provide a complete example so that others may try to reproduce it. Additionally, as you gradually simplify your code until it is small enough to post here, or on DPaste, you may find the cause faster yourself. Ivan Kazmenko.
Re: Get complete function declaration
On Tuesday, 18 July 2017 at 13:35:49 UTC, SrMordred wrote: There is a way to get the full function(or any other structure) declaration with traits? Or I will have to mount it with std.traits functions? eg. void add(int x, int y){} GetFullFunctionDeclaration!add; //return "void add(int x, int y)" There are several function traits in std.traits (see https://dlang.org/phobos/std_traits.html), which can hopefully be combined to reconstruct a function declaration. I don't see a single method which would do what you want out of the box. Perhaps there is none, since different use cases would require different small subsets of features, and all the orthogonal features are already available. Ivan Kazmenko.
Re: Avoid if statements for checking neighboring indexes in a 2D array
On Monday, 17 July 2017 at 07:14:26 UTC, Andrea Fontana wrote: Probably using ndslice library could help you! Unfortunately, that's not possible on most online contest platforms like Codeforces. For each programming language and compiler available, only the most basic package is usually installed on the server. There is a mix of reasons involved (historical, maintenance, choice of libraries, more equality for different languages, etc.). That means, e.g., no numpy for Python, no Boost for C++, and no third-party libraries for D. Ivan Kazmenko.
Re: Avoid if statements for checking neighboring indexes in a 2D array
On Sunday, 16 July 2017 at 21:50:19 UTC, kerdemdemir wrote: Process(row-1,column-1, maxrow, maxcolumn); Process(row,column-1, maxrow, maxcolumn); Process(row+1,column-1, maxrow, maxcolumn); Process(row-1,column, maxrow, maxcolumn); Process(row+1,column, maxrow, maxcolumn); Process(row-1,column+1, maxrow, maxcolumn); Process(row,column+1, maxrow, maxcolumn); Process(row-1,column+1, maxrow, maxcolumn); One of "row-1,column+1" should actually be "row+1,column+1". That's where the mentioned ways help. As for the problem itself, it can be solved without finding connected components. I won't post the solution right away because it is potentially a spoiler. See http://codeforces.com/blog/entry/53268 for problem analysis (828B) and http://codeforces.com/contest/828/submission/28637184 for an example implementation in D. Ivan Kazmenko.
Re: Avoid if statements for checking neighboring indexes in a 2D array
On Sunday, 16 July 2017 at 10:37:39 UTC, kerdemdemir wrote: My goal is to find connected components in a 2D array for example finding connected '*' chars below. x x x x x x x x x x x x x x * * x x x x * * x x x x x * * x * x x x x x ... Is there any better way to achieve this with cool std functions like enumerate or iota without needing to write eight if checks? I don't know of a library facility to do this. Still, there is a language-agnostic way to make it more concise. Instead of repeating eight similar blocks, define an array of delta-rows and delta-columns to neighboring cells, and use that array in a loop. A complete example follows: - import std.algorithm, std.array, std.range, std.stdio; immutable int dirs = 8; immutable int [dirs] dRow = [-1, -1, -1, 0, +1, +1, +1, 0]; immutable int [dirs] dCol = [-1, 0, +1, +1, +1, 0, -1, -1]; char [] [] arr; int componentSizeRecur (int row, int col) { int res = 1; arr[row][col] = 'x'; foreach (dir; 0..dirs) { auto nRow = row + dRow[dir]; auto nCol = col + dCol[dir]; if (arr[nRow][nCol] == '*') res += componentSizeRecur (nRow, nCol); } return res; } void main () { arr = ["xxx", "*xx", "xx**xxx", "xx**x*x", "xxx", ].map !(line => line.dup).array; foreach (row; 0..arr.length) foreach (col; 0..arr.front.length) if (arr[row][col] == '*') writeln (componentSizeRecur (row, col)); } - If the neighbors array is regular and known in advance (like, 4 edge-connected cells, or 8 corner-connected cells as here), you may also like to loop over possible deltas and pick the good ones, like below: - int componentSizeRecur (int row, int col) { int res = 1; arr[row][col] = 'x'; foreach (dRow; -1..+2) foreach (dCol; -1..+2) if (dRow || dCol) { auto nRow = row + dRow; auto nCol = col + dCol; if (arr[nRow][nCol] == '*') res += componentSizeRecur (nRow, nCol); } return res; } - I have to make two additional notes. 1. This works only if the border does not contain '*' characters. To make it work without that restriction, either add two sentinel rows and columns at the four borders of the array, or put an if on nRow and nCol before using them. 2. The recursive solution can eat up lots of stack. If you intend using it on large arrays, make sure you don't hit the stack size limit of the environment. On Windows, it can be achieved by a compiler switch like "-L/STACK:268435456". On Linux, the "ulimit" command may help. Ivan Kazmenko.
Re: implib.exe no output files
On Monday, 19 June 2017 at 23:11:29 UTC, Joel wrote: On Sunday, 18 June 2017 at 09:48:31 UTC, Ivan Kazmenko wrote: On Sunday, 18 June 2017 at 07:41:27 UTC, Joel wrote: I got the file here: http://ftp.digitalmars.com/bup.zip It works on other computers. I was trying to update to the latest DAllegro (https://github.com/SiegeLord/DAllegro5). Though, I used another computer for the lib files and still couldn't get the latest DAllegro5 working. The .bat files in https://github.com/SiegeLord/DAllegro5 work fine for me. Could you please be more specific about what exactly you are doing, and what went wrong? Keep in mind that you need Allegro binaries (e.g. from http://liballeg.org/download.html#windows) to use implib. Ivan Kazmenko. I have the dll's in the same directory where I run the create lib .bat file. It displays the normal stuff, but no lib files! I'm wondering if implib needs to be worked on. Sorry, that's still not specific enough. I've just tested this in a fresh directory: 1. Get https://github.com/SiegeLord/DAllegro5 2. Get https://github.com/liballeg/allegro5/releases/download/5.2.2.0/allegro-mingw-gcc6.2.0-x86-static-5.2.2.zip 3. Put, for example, allegro-5.2.dll from the archive to DAllegro5 directory. 4. Run create_import_libs.bat, here is the output: - ...>rem This batch file creates import dlls in the current folder and strips the version number ...>rem because OPTLINK sucks. Digital Mars Import Library Manager Version 7.6B1n Copyright (C) Digital Mars 2000. All Rights Reserved. Input is a Windows NT DLL file 'allegro-5.2.dll'. Output is a Windows NT import library. Digital Mars Import Library Creator complete. - 5. Now I got allegro.lib in the directory. Which of these steps fails for you, and how? Ivan Kazmenko.
Re: implib.exe no output files
On Sunday, 18 June 2017 at 07:41:27 UTC, Joel wrote: I got the file here: http://ftp.digitalmars.com/bup.zip It works on other computers. I was trying to update to the latest DAllegro (https://github.com/SiegeLord/DAllegro5). Though, I used another computer for the lib files and still couldn't get the latest DAllegro5 working. The .bat files in https://github.com/SiegeLord/DAllegro5 work fine for me. Could you please be more specific about what exactly you are doing, and what went wrong? Keep in mind that you need Allegro binaries (e.g. from http://liballeg.org/download.html#windows) to use implib. Ivan Kazmenko.
Re: Help with an algorithm!
On Thursday, 15 June 2017 at 13:41:07 UTC, MGW wrote: On Thursday, 15 June 2017 at 13:16:24 UTC, CRAIG DILLABAUGH wrote: The purpose - search of changes in file system. Sorting is a slow operation as well as hashing. Creation of a tree, is equally in sorting. So far the best result: foreach(str; m2) { bool fFind; int j; foreach(int i, s; m1) { if(str == s) { fFind = true; j = i; break; } } if(!fFind) { rez ~= str; } else {m1[j] = m1[$-1]; m1.length = m1.length - 1; } } Ugh. This can work as slow as length-of-m1 *multiplied* by length-of-m2. For 5,000,000 strings, it is 5,000,000 * 5,000,000 = 25,000,000,000,000. Granted, if you run it very often, the arrays are almost equal, and it's closer to linear. But once there are substantial changes between two consecutive runs, this approach is seriously screwed. Sorting would work in length-of-array * log(length-of-array). For 5,000,000 strings, it is 5,000,000 * 23 = 115,000,000. This is ~217,391 times better than your method above. May be a bit slower because of long common prefixes. Anyway, a couple of seconds at most. How fast you need it to be? Did you actually try it? Ivan Kazmenko.
Re: Help with an algorithm!
On Thursday, 15 June 2017 at 06:06:01 UTC, MGW wrote: There are two arrays of string [] mas1, mas2; Size of each about 5M lines. By the size they different, but lines in both match for 95%. It is necessary to find all lines in an array of mas2 which differ from mas1. The principal criterion - speed. There are the 8th core processor and it is good to involve a multithreading. The approaches which come to mind are: 1. Sort both arrays, then traverse them in sorted order, like in merge step of merge sort: sort (mas1); sort (mas2); size_t index1 = 0; foreach (str2; mas2) { while (index1 < mas1.length && mas1[index1] < str2) index1 += 1; if (mas1[index1] != str2) writeln (str2); } Sorting takes O (n log n * c) time, where n is the size of the arrays, and c is the expected time of two strings comparison when sorting. The subsequent step is O (n * c) which is faster than sorting. 2. Hashing. Just put the contents of the first array into a bool [string], and then, for each string from the second array, check whether it is contained in the associative array. The time will be O (total length of all strings) multiplied by a moderate constant, unless the strings are designed specifically to generate hash collisions, in which case it will be slower. 3. Trie. Similar to hashing, but the constant multipliers will be much higher unless the strings have large common prefixes. Whether we can do faster depends on context. For example, if the strings tend to all have long common prefixes, any string comparison will be slow, but otherwise it can be thought of as taking constant time. Ivan Kazmenko.
Re: D now available on Codefights.com
On Wednesday, 14 June 2017 at 08:32:43 UTC, Dsby wrote: On Wednesday, 14 June 2017 at 01:17:12 UTC, Ivan Kazmenko wrote: Hey, The site https://codefights.com is a place to test and improve your programming skills. The challenges include interview-type problems, shortest code contests, duels with other coders, monthly tournaments, and more. If you perform well, you can opt in to get connected with partner companies for job opportunities. [...] How can I comment other Code? Currently, there are comments for problems and contests. But for individual solutions, the only feedback possible right now is thumbs-up (in the upper right corner). However, you can suggest this feature on the forum :) .
D now available on Codefights.com
Hey, The site https://codefights.com is a place to test and improve your programming skills. The challenges include interview-type problems, shortest code contests, duels with other coders, monthly tournaments, and more. If you perform well, you can opt in to get connected with partner companies for job opportunities. Among available languages, there are C++, C#, Go, Java, Python, Ruby, Swift, and others. A few days ago, D was added to this list. After a problem is solved or a contest is over, others' solutions in all languages can be seen. To me, the major appeal of the site is that many of the problems are easy. So they take only a few minutes to solve, and the others' solutions are short and readable, often showcasing different approaches and language features. If you got interested, go give it a try! Ivan Kazmenko.
Re: DMD [-O flag] vs. [memory allocation in a synchronized class]
On Thursday, 8 June 2017 at 15:35:06 UTC, Ivan Kazmenko wrote: Perhaps a regression should be filed, or searched for, at issues.dlang.org. I can do it, but not right now, and would be glad if someone beats me to it. Reported: https://issues.dlang.org/show_bug.cgi?id=17481
Re: DMD [-O flag] vs. [memory allocation in a synchronized class]
On Thursday, 8 June 2017 at 11:41:40 UTC, realhet wrote: I've managed to narrow the problem even more: //win32 dmd -O class Obj{ synchronized void trigger(){ new ubyte[1]; } } void main(){ auto k = new shared Obj; k.trigger; } This time I got a more sophisticated error message: object.Error@(0): Access Violation 0x7272456D in SymInitialize 0x00402667 0x00402A97 0x00402998 0x004022A0 0x76F13744 in BaseThreadInitThunk 0x773B9E54 in RtlSetCurrentTransaction 0x773B9E1F in RtlSetCurrentTransaction I can reproduce this under win32, and it breaks somewhere between 2.068.2 and 2.069.0. The move instructive message with "dmd -O -g": object.Error@(0): Access Violation 0x0065 0x00402C33 in _d_newarrayU 0x004022EB in _d_newarrayT 0x00402A7F in scope void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() 0x00402980 in _d_run_main 0x00402288 in main at C:\a.d(8) 0x757F336A in BaseThreadInitThunk 0x77409902 in RtlInitializeExceptionChain 0x774098D5 in RtlInitializeExceptionChain Perhaps a regression should be filed, or searched for, at issues.dlang.org. I can do it, but not right now, and would be glad if someone beats me to it. Ivan Kazmenko.
Re: Why does phobos have collisions?
On Wednesday, 7 June 2017 at 10:01:30 UTC, Mike B Johnson wrote: Error: template std.algorithm.mutation.strip cannot deduce function from argument types !()(string), candidates are: src\phobos\std\algorithm\mutation.d(2280): std.algorithm.mutation.strip(Range, E)(Range range, E element) if (isBidirectionalRange!Range && is(typeof(range.front == element) : bool)) \src\phobos\std\algorithm\mutation.d(2287): std.algorithm.mutation.strip(alias pred, Range)(Range range) if (isBidirectionalRange!Range && is(typeof(pred(range.back)) : bool)) This is on a line of code that simply strips away a string... and works fine when using standard strip(without importing std.algorithm)... but when importing std.algorithm too, those errors pop up... seems like a defect. Actually, it looks like the std.algorithm[.mutation] is imported but std.string isn't. As std.algorithm's strip is more generic, it cannot assume what's the "whitespace" to be stripped, so it's not callable without explicitly specifying what to strip. I've experienced this too, and it's really a bit confusing the first time it happens. Ivan Kazmenko.
Re: Rosetta Commatizing numbers
On Thursday, 1 June 2017 at 08:45:23 UTC, Solomon E wrote: On Wednesday, 31 May 2017 at 15:44:51 UTC, Ivan Kazmenko wrote: So, two custom calls, two minor changes, no sweat. Is everything right now? Even if not: that was fast, we can do another iteration. When we have a short readable solution with no special cases, the first few changes are going to be easy. Ivan Kazmenko. I followed that advice, and found and fixed more bugs that were lurking in the original and in my complications. When the number begins with a decimal point, that's an edge case none of the earlier versions were handling right. I added a regression test for that. I just posted my latest version at Rosetta, without the unnecessary complications. I hope you like it better. http://rosettacode.org/wiki/Commatizing_numbers#D (The complications weren't totally useless though. Without trying the complications, I wouldn't have tested enough to make as much improvement as I have. Overcomplicated features are something to avoid releasing, except in a repo folder of extras for other programmers to try fiddling with, and Rosetta code isn't exactly that.) I very much like the current version. It is concise, has no arbitrary constants in implementation, and does the job better than the version before your edits. As for commatizeSpec (which is currently removed), I still believe it is too magically specialized to be useful. But as long as vanilla commatize is available, I'd see commatizeSpec as just a way to run the tests, and be fine with it. Thank you for bearing with me, and being a better listener than I am. Ivan Kazmenko.
Re: Rosetta Commatizing numbers
On Wednesday, 31 May 2017 at 13:27:24 UTC, Solomon E wrote: Fine, by the numbers: 1. pi has the commas start at the wrong digit, and doesn't follow the explicit instructions to use spaces as the separator and a grouping of 5 Can be solved by calling the function with a right set of parameters: start = 6 and step = 5. That's what function parameters are for. Here, I understand that a real-world solution would try to center around the decimal point. There are, however, two reasons not to do so. First, it is not required in the problem statement. Second, the solutions in other languages don't interpret the statement like that, and instead, just add a parameter to start reading from a certain point. Remember that one of the main purposes of Rosettacode is to provide a translation from one language to another. There are other places on the web for solving the problems in the best possible way. 2. There are no newlines (although the input is the list of lines to be "commatized" not concatenated.) write -> writeln 3. Zimbabwe dollars are given commas, against the explicit request to have dots. (That would be undesirable in the real world, not just in this silly example, because comma is used as a decimal point in the Zimbabwe press, and spaces for thousands separators.) Can be solved by calling the function with a right set of parameters: ins = '.'. That's what function parameters are for. 4. The second number in the line ===US$0017,440 millions=== (in 2,000 dollars) is "commatized" which is against the explicit instructions to "commatize" the first number only, given in the task description and explained on the task's talk page. replaceAll -> replaceFirst 5. The exponent in 123.e8000 is "commatized" which is against explicit and repeated instructions not to "commatize" exponents. replaceAll -> replaceFirst 6. (The commas in the Eddington number are acceptable enough.) OK. 7. The year in 6/9/1946 is "commatized" against explicit instructions to "commatize" only the first number field. It was discussed in the task's talk page that years shouldn't be commatized, and that's easy to avoid by never "commatizing" past the first number. replaceAll -> replaceFirst So, two custom calls, two minor changes, no sweat. Is everything right now? Even if not: that was fast, we can do another iteration. When we have a short readable solution with no special cases, the first few changes are going to be easy. For the Eddington number, the task didn't explicitly state to use spaces in that long a number, but the task does say there should be spaces in the digits of pi, which leaves open to interpretation whether that's a special request or a rule that could apply to any sufficiently long number, AND the task includes a reference to a Wikipedia page on the number that does use spaces. Here, I'd say you are greatly overthinking the problem. The other language solutions to Rosetta tasks may be "inspirational" in some ways, but there are also errors in them, at least for this task, that would be found if they were fully tested. They're made by human beings, and Rosetta code is just a game. It's not something that's been around as long as the older languages used there have existed, to look up to solutions in old languages with awe as time-worn and carved in stone. If you see a problem, ~10 solutions, and think all of them have serious issues, you may well be right. But it is also likely that all other solution authors read the problem differently. Which leaves an open formal question whether you are reading it correctly. As well as an open informal question whether enforcing your reading is a good goal, keeping in mind that Rosettacode is a collection of translations. - If you still insist you are doing the right thing and all others are wrong, let's agree to disagree on that, and please just leave the original solution there by introducing two versions. Ivan Kazmenko.
Re: Rosetta Commatizing numbers
On Wednesday, 31 May 2017 at 04:31:14 UTC, Ivan Kazmenko wrote: Now, where is the old version wrong? ... Actually, it also changes every number in the string, not only the first one as required. Because of that, it also fails the "do not touch the exponent" requirement. Sadly, both are not covered by the examples. The program is perhaps easily fixed by changing replaceAll into replaceFirst. As for adding examples to better check the requirements, I don't know Rosettacode's policy for that.
Re: Rosetta Commatizing numbers
On Tuesday, 30 May 2017 at 10:54:49 UTC, Solomon E wrote: I ran into a Rosetta code solution in D that had obvious errors. It's like the author or the previous editor wasn't even trying to do it right, like a protest against how many detailed rules the task had. I assumed that's not the way we want to do things in D. ... Does anyone have any thoughts about this? Did I do right by D? I'd say the previous version (by bearophile) suited the task much better, but both aren't perfect. As a general note, consider the following paragraph of the problem statement: "Some of the commatizing rules (specified below) are arbitrary, but they'll be a part of this task requirements, if only to make the results consistent amongst national preferences and other disciplines." This literally means that, while there are complex rules in the real world for commatizing numbers, the problem is kept simple by enforcing strict rules. The minute concerns of the Real World, like "Current New Zealand dollar format overrides old Zimbabwe dollar format", are irrelevant to the formal problem being solved. Perhaps the example inputs section ("Strings to be used as a minimum") gets misleading, but that's what they are: examples, not general rules. By the way, as it's a wiki page, problem statement text could also be improved ;) . Why? For example, look at Indian numbering system where commatizing is visibly different (https://en.wikipedia.org/wiki/Indian_numbering_system) - and we don't know whether the string should use it or not without the context. Or consider that hexadecimal numbers are usually split in groups of four digits, not three - and we don't know whether a [0-9]+ number is decimal or hexadecimal without the context. See, trying to provide an ultimate solution to real-world commatizing, while keeping it a single function without the context, can't possibly succeed. What can be done, then? Well, the page authors already did the difficult part for us: they extracted the essence of a complex real-world problem into a small set of formal rules, which are now the formal problem statement. Now comes the easy part: to do exactly what is asked in the problem statement. The flexibility comes from having function parameters. If we have a solution to a formal problem, using it for the real-world version of the problem is either just specifying the right parameters (hopefully), or changing the function if the real world gets too complex for it. In the latter case, the more short and readable the existing solution is, the faster can we change the function to suit our real-world case. - Now, where is the old version wrong? Turns out it just calls the function with default parameters for every line of input - which is wrong since the first two input lines need to be handled specially. Well, that's what the function parameters are for. To have a correct solution, we have to use custom parameters for the first two lines of input. The function itself is fine. Your solution addresses this problem by special-casing the inputs inside the function, perhaps because of the misleading inputs section in the problem statement. That's a wrong approach. First, it introduces magic numbers 33 and 36 into the code, which is a bad programming practice (see here: https://en.wikipedia.org/wiki/Magic_number_(programming)#Unnamed_numerical_constants). Second, it's plain wrong. According to the problem statement, we don't have these rules for every possible line of >33 standalone decimals, or >36 characters in total. We just have to call our function with a concrete set of custom parameters for one concrete example, and other set of parameters for another example. That's to demonstrate that our function accepts and makes proper use of custom parameters! Special-casing example inputs inside the function is not a solution: if we go down this path, the perfect solution would be a bunch of "if" statements for every possible example input producing the respective example outputs, and empty function for all other possible inputs. So, how do we call with special parameters? Currently, we can look at every other language except C# as inspiration: ALGOL 68, J, Java, Perl 6, Phix, Racket, and REXX. Your solution also has a good way to check example inputs: a unittest block. It even shows one of D's strengths compared to other languages. And there, you do use custom parameters to check that the function works. A good approach would be to put all the examples in the unittest instead of reading them from a file. This way, the program will be immediately usable and runnable: no need to create an additional arbitrarily-named file just to test it. - All in all, the only thing I'd change in bearophile's solution is to remove the file reading loop, add the unittest block from your solution instead, and place all the examples there. Printing the result does not
Re: How to avoid throwing an exceptions for a built-in function?
On Wednesday, 10 May 2017 at 12:40:41 UTC, k-five wrote: I have a line of code that uses "to" function in std.conv for a purpose like: int index = to!int( user_apply[ 4 ] ); // string to int When the user_apply[ 4 ] has value, there is no problem; but when it is empty: "" it throws an ConvException exception and I want to avoid this exception. currently I have to use a dummy catch: try{ index = to!int( user_apply[ 4 ] ); } catch( ConvException conv_error ){ // nothing } I no need to handle that, so is there any way to prevent this exception? I assume that an empty string is a valid input then. The question is, what value do you want `index` to have when the string is empty? Maybe the old value, or some constant? In any case, to better express your intent, you may write something like: if (user_apply[4] != "") { index = to !(int) (user_apply[4]); } else { index = ...; // specify whatever your intent is } This way, the code is self-documenting, and the program still throws when `user_apply[4]` is neither empty nor an integer, which may be the right thing to do in the long run. Ivan Kazmenko.
Re: [OT] Algorithm question
On Tuesday, 2 May 2017 at 10:35:46 UTC, Ivan Kazmenko wrote: I hope some part of the idea is still salvageable. For example, what if we put the intervals in a queue instead of a stack? I tried to implement a similar approach, but instead of a queue or a stack, I used a random-access array of intervals. Sadly, it is still far from uniform, since it does not take interval lengths into account, and I don't see how to do that without at least O(log n) time per interval insertion or deletion. Implementation and empiric frequencies for n=5 elements in a permutation: http://ideone.com/3zSxLN Ivan Kazmenko.
Re: [OT] Algorithm question
On Monday, 1 May 2017 at 21:54:43 UTC, MysticZach wrote: On Monday, 1 May 2017 at 16:56:58 UTC, MysticZach wrote: The goal is to have the first hit be the one you return. The method: if a random pick doesn't satisfy, randomly choose the partition greater than or less than based on uniform(0..array.length-1), and do the same procedure on that partition, reusing the random index to avoid having to call uniform twice on each recursion (one to choose a partition and one to choose an index within that partition). If the probability of choosing a partition is precisely proportional to the number of elements in that partition, it seems to me that the result will be truly random, but I'm not sure. Now I'm questioning this, because if the positive cases are unevenly distributed, i.e., [11000100], the last one has about 50% chance to get picked instead of a 1 in 7 chance with my method. I guess you'd need to build a whole new array like the others are saying. A pity; it sounded nice! But yeah, once we pick the right ~half, we have to completely traverse it before paying any attention to the left ~half. I hope some part of the idea is still salvageable. For example, what if we put the intervals in a queue instead of a stack? Ivan Kazmenko.
Re: [OT] Algorithm question
On Monday, 1 May 2017 at 04:15:35 UTC, H. S. Teoh wrote: Given a set A of n elements (let's say it's a random-access range of size n, where n is relatively large), and a predicate P(x) that specifies some subset of A of elements that we're interested in, what's the best algorithm (in terms of big-O time complexity) for selecting a random element x satisfying P(x), such that elements that satisfy P(x) have equal probability of being chosen? (Elements that do not satisfy P(x) are disregarded.) I'd like to note here that, if you make use of the same P(x) many times (instead of different predicates on each call), it makes sense to spend O(n) time and memory filtering by that predicate and storing the result, and then answer each query in O(1). 3) Permutation walk: auto r = ... /* elements of A */ foreach (i; iota(0 .. r.length).randomPermutation) { if (P(r[i])) return r[i]; } /* no elements satisfy P(x) */ Advantages: if an element that satisfies P(x) is found early, the loop will terminate before n iterations. This seems like the best of both worlds of (1) and (2), except: Disadvantages: AFAIK, generating a random permutation of indices from 0 .. n requires at least O(n) time, so any advantage we may have had seems to be negated. Is there an algorithm for *incrementally* generating a random permutation of indices? If there is, we could use that in (3) and thus achieve the best of both worlds between early termination if an element satisfying P(x) is found, and guaranteeing termination after n iterations if no elements satisfying P(x) exists. Yes, there is. There are actually two variations of Fisher-Yates shuffle: (https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) 1. auto p = n.iota.array; foreach (pos; 0..n) { auto otherPos = uniform (0, pos + 1); swap (p[pos], p[otherPos]); } When we look at this after k-th iteration, the first k elements are randomly and uniformly permuted, and the rest (n-k) are left untouched. 2. auto p = n.iota.array; foreach (pos; 0..n) { auto otherPos = uniform (pos, n); swap (p[pos], p[otherPos]); } When we look at this after k-th iteration, the first k elements are a random combination of all n elements, and this combination is randomly and uniformly permuted. So, the second variation is what we need: each new element is randomly and uniformly selected from all the elements left. Once we get the first element satisfying the predicate, we can just terminate the loop. If there are m out of n elements satisfying the predicate, the average number of steps is n/m. Now, the problem is that both of these allocate n "size_t"-s of memory to start with. And your problem does not allow to shuffle the elements of the original array in place, so we do need an external permutation for these algorithms. However, there are at least two ways to mitigate that: (I) We can allocate the permutation once using n time and memory, and then, on every call, just reuse it in its current state in n/m time. It does not matter if the permutation is not identity permutation: by symmetry argument, any starting permutation will do just fine. (II) We can store the permutation p in an associative array instead of a regular array, actually storing only the elements accessed at least once, and assuming other elements to satisfy the identity p[x] = x. So, if we finish in n/m steps on average, the time and extra memory used will be O(n/m) too. I can put together an example implementation if this best satisfies your requirements. Ivan Kazmenko.
Re: Problem with using readln.
On Sunday, 30 April 2017 at 02:07:48 UTC, JV wrote: Hello i'm kinda new to D language and i wanted to make a simple program but somehow my input does no go to my if statements and just continues to ask for the user to input.Kindly help me One way would be: import std.stdio; int x; readf (" %s", ); The "%s" means "default format for the type", which is I believe "%d" (decimal) for the int type. The space before "%s" is to skip all whitespace before the actual input, it will matter when you read your second integer: readf ("%s%s", , ); // error, got space for y instead of a digit readf ("%s %s", , ); // ok Another way is: import std.conv, std.stdio, std.string; int x = readln.strip.to!int; Here, we read the line with readln, strip the trailing whitespace with strip, and convert the resulting string to an int with to!int. Also, you might want to look at the corresponding chapter in Ali Cehreli's book: http://ddili.org/ders/d.en/input.html Ivan Kazmenko.
Re: Release D 2.074.0
On Monday, 10 April 2017 at 20:09:40 UTC, Martin Nowak wrote: Glad to announce D 2.074.0. [...] http://dlang.org/download.html http://dlang.org/changelog/2.074.0.html Thank you for producing the releases! I noticed that the backend license in this release (at least the Windows .7z version) is still the same, as well as the license.txt file at its root. Is it that there was simply not enough time to reflect the recent changes? And after the changes are incorporated, do you plan to alter the license texts in the previous releases as well? Ivan Kazmenko.
Re: Zcoin implementation bug enabled attacker to create 548, 000 Zcoins
On Thursday, 9 March 2017 at 15:42:22 UTC, qznc wrote: I'm curious. Where does it make sense for opEquals to be non-pure? Likewise opCmp, etc. An example would be tracking the number of comparisons made. This sounds like debug information (and then, debug statement can be used to escape purity), but perhaps may be applied beyond simple debugging and profiling. Ivan Kazmenko.
Re: Can you read the next line while iterating over byLine?
On Thursday, 2 February 2017 at 19:34:37 UTC, John Doe wrote: Thanks readln is perfect. Since I am calling readln in different places and I always need to remove the newline character I have line=line[0..$-1] all over my code. Is there are better way? "readln.strip" gives the line without the trailing newline character.
Re: Associative array literal: length wrong when duplicate keys found
On Tuesday, 31 January 2017 at 19:45:33 UTC, Ivan Kazmenko wrote: On Tuesday, 31 January 2017 at 17:20:00 UTC, John Colvin wrote: It's a bug, please report it. The initializer should be statically disallowed. Anyway, I'll file a bug report. Hmm, found it: https://issues.dlang.org/show_bug.cgi?id=15290 I'll add details about my use case to the report, for what it's worth.
Re: Associative array literal: length wrong when duplicate keys found
On Tuesday, 31 January 2017 at 17:20:00 UTC, John Colvin wrote: It's a bug, please report it. The initializer should be statically disallowed. Adding a .dup works around the problem. OK. Hmm, but the real use case was a bit more complicated, more like: - int n = 10; foreach (i; 0..n) foreach (j; 0..n) foreach (k; 0..n) ... and maybe a couple more ... if ([i: true, j: true, k: true].length == 3) {...} // i, j, k is a set of distinct values - Here, we don't know i, j and k statically, yet the problem is the same. Anyway, I'll file a bug report. By the way, you can do sets like this, avoiding storing any dummy values, only keys: struct Set(T) { void[0][T] data; void insert(T x) { data[x] = (void[0]).init; } void remove(T x) { data.remove(x); } bool opBinaryRight(string op : "in")(T e) { return !!(e in data); } // other things like length, etc. } unittest { Set!int s; s.insert(4); assert(4 in s); s.remove(4); assert(4 !in s); } Yeah, thanks for the recipe! I usually do bool [key] since it does not add much overhead, but would definitely like the real set (void[0] or otherwise) when performance matters. Ivan Kazmenko.
Re: Partial arrays reclaimed?
On Friday, 27 January 2017 at 23:22:17 UTC, Nick Sabalausky wrote: Suppose an array is being used like a FIFO: --- T[] slice; // Add: slice ~= T(); // Remove: slice = slice[1..$]; --- Assuming of course there's no other references to the memory, as this gets used, does the any of the memory from the removed elements ever get GC'd? As I see it, the line slice = slice[1..$]; effectively ends slice's in-place appending capabilities. So each append after remove will likely reallocate. You have to use assumeSafeAppend to re-enable appending in place. Here [1] is an old thread about the caveats of using built-in arrays as queues and stacks. If not in a hurry, the better option is perhaps to just write the respective wrapper structs which explicitly store indices, instead of using built-in slices and assumeSafeAppend all over the place. Ivan Kazmenko. [1] http://forum.dlang.org/post/yrxspdrpusrrijmfy...@forum.dlang.org
Associative array literal: length wrong when duplicate keys found
Hi. I wanted to check whether a few variables of the same type are all distinct, in a quick and dirty way. I tried to do it similar to Python's "len(set(value_list)) == len(value_list)" idiom by using an associative array (AA). At this point, I found out that when initializing the AA with a literal, the length is the number of keys given, regardless of whether some of them were the same. A minimized example: - import std.stdio; void main () { auto aa = [1 : 2, 1 : 3]; writeln (aa.length, " ", aa); // 2 [1:3, ] } - See, the length is 2, but iteration over aa yields only one key:value pair. Also, note the comma which is a sign of internal confusion as well. My question is, what's the state of this? Is this a bug? Or should it be forbidden to have such an initializer? Or maybe it is a feature with some actual merit? Ivan Kazmenko.
Re: Yield from function?
On Monday, 30 January 2017 at 11:03:52 UTC, Profile Anaysis wrote: I need to yield from a complex recursive function too allow visualizing what it is doing. e.g., if it is a tree searching algorithm, I'd like to yield for each node so that the current state can be shown visually. I realize that there are several ways to do this but D a yield version without additional threads would be optimal. I don't need concurrency or speed, just simple. Sounds like opApply (external iteration) may well be the way to go. It is a great tool to separate (possibly complex) iteration logic from (possibly complex) instance processing logic. Here is a random recipe: https://www.sociomantic.com/blog/2010/06/opapply-recipe An example: - import std.stdio; class Node { int value; Node left, right; this (int value_) {value = value_;} } struct InOrderViewer { Node root; int opApply (int delegate (Node) process) { void recur (Node cur) { if (cur is null) return; recur (cur.left); process (cur); // use return value here to allow break in foreach recur (cur.right); } recur (root); return 0; } } void main () { auto v1 = new Node (1); auto v2 = new Node (2); auto v3 = new Node (3); auto v4 = new Node (4); auto v5 = new Node (5); v2.left = v1; v2.right = v5; v5.left = v3; v3.right = v4; foreach (node; InOrderViewer (v2)) { writeln (node.value ^^ 2); // 1 4 9 16 25 } } - Ivan Kazmenko.
Re: size of a string in bytes
On Saturday, 28 January 2017 at 15:32:33 UTC, Nestor wrote: I want to know variable size in memory. For example, say I have an UTF-8 string of only 2 characters, but each of them takes 2 bytes. string length would be 2, but the content of the string would take 4 bytes in memory (excluding overhead for type size). As said, the byte count is indeed string.length. The number of code points can be found by std.range.walkLength, but be aware it takes O(answer) time to compute. Example: - import std.range, std.stdio; void main () { auto s = "Привет!"; writeln (s.length); // 13 bytes writeln (s.walkLength); // 7 code points } - Ivan Kazmenko.
Re: Trying to understand multidimensional arrays in D
On Thursday, 26 January 2017 at 05:20:07 UTC, Profile Anaysis wrote: (On the contrary, declarations in C or C++ looks rather unintuitive from this perspective: `T a[4][5][6]` is means that `a` is an array of 4 arrays of 5 arrays of 6 arrays of `T`. Note how we have to read left-to-right but then wrap around the string to get the meaning.) lol, I don' tknow what the last sentence means. wrap around the string? Do you mean look at the variable? For me the interpretation above is the most logical because it is a sequential operation in my mind, if you will. x of y of z and the chain can be cut off anywhere and the interpretation still be the same. This means that in `T a[4][5][6]`, the type `T[4][5][6]` is spread on both sides of the variable name `a`. In the interpretation, "`a` is an array of 4 arrays of 5 arrays of 6 arrays of `T`", note that 4, 5 and 6 are from the right side but T is from the left side. That's what I meant by wrap around.
Re: Trying to understand multidimensional arrays in D
On Thursday, 26 January 2017 at 01:47:53 UTC, Profile Anaysis wrote: does this mean that have int[][4][4] matrix_history; backwards? int[4][4][] matrix_history; this creates even a more set of problems. In short, you are right, `int[4][4][]` is a dynamic array of `int[4][4]`. In turn, `int[4][4]` is a static length-4 array of `int[4]`, and that is a static length-4 array of `int`. It's quite logical once you learn how to read it: if T is a type, then T[] is a dynamic array of that type, and T[4] is a static length-4 array of that type. So, if I have `int[2][5][7] a;` somewhere, the very last element is `a[6][4][1]`. If you are inclined to think in terms of this difference, the simple rule of thumb would be that the order of dimensions in the declaration is reversed. Also, note that if you want to have, for example, a dynamic array of 5 dynamic arrays of the same length 7 (modeling a C rectangular array, or a D static array, but with possibility to change the length of each row, as well as the number of rows), you would go with `auto a = new int [] [] (5, 7);` (initialization) The static array of 5 static arrays of length 7 is still `int [7] [5] a;` (type declaration) So the reverse only happens in type declarations. (On the contrary, declarations in C or C++ looks rather unintuitive from this perspective: `T a[4][5][6]` is means that `a` is an array of 4 arrays of 5 arrays of 6 arrays of `T`. Note how we have to read left-to-right but then wrap around the string to get the meaning.) Additionally, reading about various kinds of arrays in D might help: https://dlang.org/spec/arrays.html And more in-depth material about array slicing: http://dlang.org/d-array-article.html Ivan Kazmenko.
Re: switch to member
On Saturday, 14 January 2017 at 11:32:10 UTC, Marc Schütz wrote: You can utilize a little-known `switch` syntax trick in combination with `foreach`. Because a `foreach` over tuples is unrolled at compile time, it works even if your fields don't have exactly the same types: That looks concise. Perhaps enum Which can also be automatically filled by __traits (allMembers) or std.traits.Fields if needed.
Re: opOpAssign on object properties
On Sunday, 8 January 2017 at 18:23:34 UTC, collerblade wrote: On Sunday, 8 January 2017 at 10:03:50 UTC, Ivan Kazmenko wrote: On Sunday, 8 January 2017 at 09:22:12 UTC, collerblade wrote: [...] 1. If you want the member variable to change, naturally, you should provide a getter property which returns a reference to that variable: [...] yes i tried the reference return, but the problem is, that the setter does NOT gets called, no matter what the result type of the opOpAssign method is. I want to detect changes, but this way i still not able. A a = new A; a.location+=Point(1,1); //the private value changes, but the setter does not get called Hmm, right. The setter is not called, and it's by the spec. Which says that "a op= b" is rewritten as "a.opOpAssign !(op) (b)". Here: https://dlang.org/spec/operatoroverloading.html#op-assign So, no *assignment* happens when you call a.location+=Point(1,1). To have a side effect triggered by opAssign-ment, you can do it inside the opOpAssign function. Looking at it another way, actions with struct Point can be seen as the responsibility of struct Point. If you want to monitor these actions, do it in the code of opOpAssign function. After that, your class A can inspect the state of its corresponding Point. If normal Points don't need that, you can have a special SelfAwarePoint which has an alias this to its member Point. Alternatively, you can have two getter properties: one as const and one by reference. When the reference one gets called, you know the value of Point *may* have changed. Well, I'm out of ideas for now. If these still don't quite satisfy you, including a bigger picture of what you want to achieve may help. Ivan Kazmenko.
Re: opOpAssign on object properties
On Sunday, 8 January 2017 at 09:22:12 UTC, collerblade wrote: How can i do opOpAssign with properties?? 1. If you want the member variable to change, naturally, you should provide a getter property which returns a reference to that variable: ref Point location() @property { return m_location; } This alone solves the immediate problem. 2. Note that it is common for assignment expressions to return a reference to the result, which would, for example, make chains like "a = (b += c)" possible: ref Point opOpAssign(string op)(in Point p) if (op == "+") { x+=p.x; y+=p.y; return this; } Here's a complete working version of your example: - struct Point { float x=0,y=0; this(float _x, float _y) { x=_x; y=_y; } //opopassign for += ref Point opOpAssign(string op)(in Point p) if (op == "+") { x+=p.x; y+=p.y; return this; } } class A { public: ref Point location() @property { return m_location; } void location(in Point newlocation) @property { m_location=newlocation; } private: Point m_location; } void main() { import std.stdio; auto a= new A; a.location+=Point(1,1); writeln (a.location); // Point(1, 1) a.location+=Point(1,1); writeln (a.location); // Point(2, 2) } - Ivan Kazmenko.
Re: To use a scripting language or not to use a scripting language?
On Friday, 6 January 2017 at 14:19:34 UTC, Anton Pastukhov wrote: As a game developer I can recommend to use Lua. This language is tradtionally used in many games/game engines. Ironically, one of D's declared selling points is, according to https://dlang.org/overview.html: Who is D For? Programmers who write half their application in scripting languages the other half in native langauges to speed up the bottlenecks. D has productivity features that make using such hybrid approaches unnecessary. The use case here is arguably different. In the ideal case, game logic scripts are editable by gamers which are not necessarily programmers. Chris Wright has already given a bunch of other reasons to use a self-contained, simple, domain-specific, and limited language in such a setting. Perhaps D will some day be usable in a language-as-a-library setting which would make it possible to use for game logic scripts, too. But considering the points above, it still won't necessarily be a good idea. Some of the top games use Python (Civilization IV) and Lua (World of Warcraft, Far Cry, SimCity 4) for scripting. Ivan Kazmenko.
Re: Adding linker paths with spaces using dmd and msvc toolchain
On Friday, 30 December 2016 at 05:24:56 UTC, Jeremy DeHaan wrote: On Friday, 30 December 2016 at 04:56:59 UTC, Jerry wrote: On Friday, 30 December 2016 at 03:51:13 UTC, Jeremy DeHaan wrote: How does one correctly add a linker path that has spaces? The quotes get consumed by the command line. The way DMD spawns the linker by creating a new string with all the flags. So it smashes everything into a new string, ignoring how the string was passed into DMD. I think you can use triple quotes, """string with space""", and it should make the string passed to DMD include the string. Might be different for powershell. You mean I could do -L/LIBPATH:"""path"""? There is also the dark and dirty way of using the short DOS path, which is still maintained on Windows file system partitions. How to get DOS path: http://stackoverflow.com/questions/4051088/how-to-get-dos-path-instead-of-windows-path I can't recommend it as a long-term solution, but it sure can help when one needs things working here and now. Ivan Kazmenko.
Russian AI Cup 2016
Hi. Russian AI Cup 2016: CodeWizards is an annual online competition organized by Mail.Ru Group. This year's task is to write a bot for a simple DOTA-like game. The competition is open for international participation: starting this year, there is an English translation for everything (it may be rough at the edges though, for example, some pages may still use Russian by default, but the English version is also there). Public beta started on November 6, and the competition end is on December 25. The languages supported out-of-the-box are C++, C#, Java, Pascal, Python (2/3), and Ruby. However, the participants may translate the language-specific development package into other languages and contact the admins to enable their use on the site. Currently, the support for D, Go, and JavaScript are added this way (official announcement coming soon). My relationship with the competition is working on the D language package. I hope to take part, too. Links for the interested: Competition site: http://russianaicup.ru/ Quick start page: http://russianaicup.ru/p/quick Language package (English): https://github.com/GassaFM/raicup-2016-dlang-cgdk-en Language package (Russian): https://github.com/GassaFM/raicup-2016-dlang-cgdk-ru Ivan Kazmenko.
Re: How to list aggregate members in order of declaration at compile time?
On Friday, 11 November 2016 at 22:04:37 UTC, Jonathan M Davis wrote: ... I expect that it never occurred to Walter to specify that the order of the members mattered with tupleof and that that's why the spec doesn't say. So, use tupleof, and you can create an enhancement request in bugzilla for the spec to be made clearer about it: https://issues.dlang.org Thanks for the answer! So you think the order guarantee is likely to be just granted for .tupleof if asked for. I hope to get to creating a documentation issue/PR next week, to see more reaction. Ivan Kazmenko.
Re: How to list aggregate members in order of declaration at compile time?
On Thursday, 10 November 2016 at 10:16:44 UTC, Ivan Kazmenko wrote: I want to somehow list members of a class in the order of their declaration. Bump. Anyone? I've met my immediate goal by other means, but the general question remains. If classes are no-go, basically, any aggregate will do if the order of declarations is reliably and reproducibly known at compile time. I'm not much into compile-time reflection, yet, but I thought that's a basic operation. Otherwise, how do people, for example, approach serializing arbitrary containers reproducibly across compiler versions - or they just don't? Well, I've seen one example (Cerealed), but the implementation details there seem to contradict the current language documentation. Ivan Kazmenko.
How to list aggregate members in order of declaration at compile time?
Hi. I want to somehow list members of a class in the order of their declaration. The immediate goal is to generate a few functions, like the "default" constructor for structs but only with all the fields, or the "reader" function, but I'm interested in the general question as well. I can go the hard way and wrap every declaration into something that will collect them and then list in the right order. The problem is, the declarations won't look normal then. The documentation for __traits (allMembers, ...), __traits (derivedMembers, ...) and the like [1] explicitly says that the order is not defined. Still, I've looked at Atila Neves' Cerealed serializer library, and it does use them [2]. Does it mean the order is unlikely to change at this point? The documentation for std.traits' RepresentationTypeTuple [3] says things are listed in topological order, which formally does not restrict the order for flat structures again. And the underlying implementation [4] of Fields uses .tupleof class property which, in turn, does not list any guarantees on the order [5]. So I'm confused. What is considered the right way to list members when I care about their linear order? Ivan Kazmenko. [1] https://dlang.org/spec/traits.html#derivedMembers [2] https://github.com/atilaneves/cerealed/blob/master/src/cerealed/cereal.d#L467 [3] https://dlang.org/phobos/std_traits.html#RepresentationTypeTuple [4] https://github.com/dlang/phobos/blob/10cd84a/std/traits.d#L2279 [5] https://dlang.org/spec/class.html#class_properties
Re: Function Proposal: std.algorithm.iteration : cumulativeSum
On Tuesday, 1 November 2016 at 22:13:29 UTC, e-y-e wrote: On Tuesday, 1 November 2016 at 22:09:50 UTC, e-y-e wrote: On Tuesday, 1 November 2016 at 22:06:36 UTC, Ivan Kazmenko wrote: ... damn, that was a typo [cumulativeFold -> cumulativeSum] similarly, in the first para, cumulativeSum!((a, b) => a + b)(r, s) -> cumulativeFold!((a, b) => a + b)(r, s) Ouch, and I completely misread the TL;DR paragraph, sorry for the noise! It's logical to have cumulativeSum specialized from cumulativeFold when sum is a specialization of fold. I have yet to write a program which relies on Kahan summation, but I can imagine that being useful. Ivan Kazmenko.
Re: Function Proposal: std.algorithm.iteration : cumulativeSum
On Tuesday, 1 November 2016 at 21:52:40 UTC, e-y-e wrote: I'd like to propose the function cumulativeFold as a new addition to std.algorithm.iteration. I have already opened a pull request [1] for this addition so the full implementation is available there. The function signatures are: DMD 2.072 just got cumulativeFold: https://dlang.org/changelog/2.072.0.html#std-algorithm-iteration-cumulativeFold https://dlang.org/phobos/std_algorithm_iteration.html#cumulativeFold
Re: 16MB static arrays again...
On Wednesday, 24 August 2016 at 07:50:25 UTC, Tomer Filiba wrote: #WEKA #INDUSTRY I found this post from 2007 http://forum.dlang.org/post/fdspch$d3v$1...@digitalmars.com that refers to this post from 2006 http://www.digitalmars.com/d/archives/digitalmars/D/37038.html#N37071 -- and I still don't realize, why do static arrays have this size limit on them? Heh, I'm the OP of the 2006 thread. Ten years passed, and I've learned to use dynamic arrays in D with negligible loss of performance most of the time. But of course I'd still like to have no such artificial limit. Ivan Kazmenko.
Re: D for competitive programming
Hi! On Thursday, 28 July 2016 at 21:20:29 UTC, urxvt1 wrote: I wanted to try topcoder problems (never used this site before) and I found out that it doesn't support dlang. They only have c++, java, c#, vb.net, python languages. It would be great to see D on this list. I highly doubt TopCoder would adopt D anytime soon. TopCoder definitely had their time as The Site for Competitive Programming, but that was like ten years ago. For a very long time already, they don't actively evolve algorithmic competitions, and seem to be driven by other tracks which actually make them some money. So, unless there are plenty of clients who want to do crowdsourcing in D and use TopCoder platform for that, it's unlikely to be added. Fortunately, competitive programming sites are now aplenty, so one can focus on other sites instead. I've also checked google code jam statistics and unfortunately D isn't very popular here compared to say golang or scala. https://www.go-hero.net/jam/16/languages https://www.go-hero.net/jam/15/languages https://www.go-hero.net/jam/14/languages https://www.go-hero.net/jam/13/languages D is at an odd position there, because only a few use it, yet some of them (like Kazuhiro Hosaka) are strong competitors and get to the finals. Generally, as already mentioned, there are a number of competition series where one can use any language, since only the answers are checked: Google Code Jam (https://code.google.com/codejam) Facebook Hacker Cup (https://facebook.com/hackercup) Internet Problem Solving Contest (https://ipsc.ksp.sk) ICFP Contest (https://icfpc2016.blogspot.com, weekend contest) Al Zimmermann's Programming Contests (https://azspcs.com, three months long) Most of the above happen only once a year though. Among the sites which actually compile your code, there are a few which already support D, again, some already mentioned: Codeforces (http://codeforces.com, DMD 2.069.2 32-bit) AtCoder (https://atcoder.jp, all three: DMD/GDC/LDC; the site is new to international community, but competitive programming in D looks strong in Japan) HackerRank (https://hackerrank.com, DMD 2.071.1) CodeChef (https://codechef.com, outdated GDC 4.9.2 which I had trouble with, same platform as SPOJ) Yandex.Contest (https://contest.yandex.com, outdated GDC 4.9 but didn't give me trouble on top of that) And these are only the sites I tried personally. Sure, there are other competition sites which also support D. On the other hand, the two competitions which have the most influence on the competitive programming community are IOI for high school students and ACM ICPC for teams from universities, and their many national and local sub-rounds. These are pretty conservative when it comes to programming languages: in the last 20 years, the only languages which got at least some time frame and degree of support are Pascal, C, C++, Java and Python. There are a number of problems when reasoning for the adoption here. One of them is the chicken - egg problem revisited. The competitions have multi-stage selection process: there are at least regional, national and international rounds for IOI, and quaterfinals, semifinals and World Finals for ACM ICPC. If the world final round doesn't support some language X, regional rounds are reluctant to support X as well, since by doing that, they would allow strong competitors using X to pass to the later round, but no support for their tool exists in that round, which certainly has its downsides. On the other hand, if the world final round starts to support X without massive desire for such support from regional rounds, they would end up spending resources for very little gain. Another problem sounds like this: if support for language X is added, this opens a flurry of requests to support dozen of other comparable languages. For an established international competition, this means quite a bit of research must be done to choose what to support and what not to. And for each language getting support, it means either a great increase in effort to ensure every problem can be comfortably solved in every language, or only limited support, which also has its downsides. The latter is what happens in the case of Python: it is not guaranteed that every problem will be solvable in Python, and, in all likelihood, some problems will really be unsolvable. That said, for competitions which already support quite a few languages but not D (among what I've seen, HackerEarth and CodeFights sites come to mind), one could have more success in persuading them to include a D compiler as well. When many languages are already onboard, adding another one is more likely to be straightforward when motivation is present. Ivan Kazmenko.
Re: add attributes to debug
On Sunday, 24 July 2016 at 21:33:20 UTC, Gorge Jingale wrote: To allow for different debug versions without having to go full blown version(). @mem debug do something memory wise @see debug write a message to console I don't get what would be the benefit. Currently, you can write that like: version (debug_mem) {do something memory wise} version (debug_see) {write a message to console} In my opinion, saving a few characters here does not get anywhere near a good reason to add language complexity. Ivan Kazmenko.
Re: Newbie: Error parsing csv file with very long lines
On Saturday, 23 April 2016 at 10:40:13 UTC, salvari wrote: It seems to be really simple, I read the columns name with no problem. But as soon as the program parses the first line of data, the array containing the columns names seems to be overwrited. Another possibility yet not mentioned is to change foreach(line; stdin.byLine()) into foreach(line; stdin.byLineCopy()) to make the older lines' contents available after you read the next line.
Re: Ada-Style Modulo Integer Types
On Friday, 22 April 2016 at 17:37:44 UTC, Nordlöw wrote: Have anybody implement Ada-style modulo types https://en.wikibooks.org/wiki/Ada_Programming/Types/mod I've implemented a proof-of-concept for algorithmic programming competitions [1]. In these competitions, quite a few problems ask to calculate the result modulo some large prime number. The usual idea is that, this way, you still have to solve the underlying algorithmic problem, but the magnitude of calculated values does not affect your algorithmic complexity. Disclaimer: it is incomplete and tuned for the competitions, and thus not ready for general use. For the record, there is also an implementation of modulo integer for the same problem in C++ by Vladislav Isenbaev. Note that the solutions themselves are not the same, so the timing can't be compared directly. Ivan Kazmenko. [1] http://codeforces.com/contest/628/submission/16212299 [2] http://codeforces.com/contest/628/submission/16610362
Re: Compiling with -profile=gc makes program crash - why?
On Thursday, 21 April 2016 at 10:57:12 UTC, Ivan Kazmenko wrote: Humm, when I searched whether it should work, I only found a reassuring post by Walter[1] almost a year ago. The issue tracker does not seem to contain an entry either. Perhaps I should create one, then. [1] http://forum.dlang.org/post/mia2kf$djb$1...@digitalmars.com Issue created: https://issues.dlang.org/show_bug.cgi?id=15947
Re: Compiling with -profile=gc makes program crash - why?
On Thursday, 21 April 2016 at 09:23:26 UTC, tcak wrote: I'm trying to use DMD option "-profile=gc". You are using "spawn". So it is a multithreaded program. -profile=gc doesn't work with multithreadd programs. Always creates problems. Humm, when I searched whether it should work, I only found a reassuring post by Walter[1] almost a year ago. The issue tracker does not seem to contain an entry either. Perhaps I should create one, then. [1] http://forum.dlang.org/post/mia2kf$djb$1...@digitalmars.com
Re: Compiling with -profile=gc makes program crash - why?
On Wednesday, 20 April 2016 at 22:27:36 UTC, Ivan Kazmenko wrote: I'm trying to use DMD option "-profile=gc". With this option, the following simple program crashes with 2.071.0 down to 2.069.0 but still works on 2.068.2. The command line is "dmd -g -profile=gc prfail1.d" on Windows (compiled to 32-bit by default). Ouch, meant to post to D.learn. Sorry! Well, perhaps no point in reposting now.
Compiling with -profile=gc makes program crash - why?
I'm trying to use DMD option "-profile=gc". With this option, the following simple program crashes with 2.071.0 down to 2.069.0 but still works on 2.068.2. The command line is "dmd -g -profile=gc prfail1.d" on Windows (compiled to 32-bit by default). -prfail1.d- import std.concurrency; void someWork () {auto x = [1];} void main () {spawn ();} - The crash happens almost always, >90% of runs of the compiled program. Here's the error output: - object.Error@(0): Access Violation 0x00409651 in nothrow int rt.profilegc._staticDtor407().__foreachbody2(ref immutable(char)[], ref rt.profilegc.Entry) 0x00409986 in void rt.profilegc.__moddtor() 0x00427444 in __threadstartex 0x77869ED2 in RtlInitializeExceptionChain 0x77869EA5 in RtlInitializeExceptionChain - With added "-m64", it just crashes and does not print anything. Am I doing something wrong, or is it a 2.069 regression? Interestingly, a modified version does not crash: -prfail2.d- import std.concurrency; void someWork () {auto x = [1];} void main () {spawn (); someWork ();} - I was curious if this guarantees that the spawned thread finishes before the main thread, but the third example, also crashing, seems to contradict that: -prfail3.d- import std.concurrency; void someWork () {auto x = [1];} void main () { spawnLinked (); try {receive ((int) {});} catch (LinkTerminated o) {} } - Ivan Kazmenko.
Mention GSoC on the front page?
Hi, I just navigated to https://gentoo.org (home of Gentoo Linux), and among the scarce news items on the front page, the topmost is about Gentoo and Google Summer of Code. It links to two detailed pages on how and why to get involved. The thought is: maybe GSoC deserves a place on the front page of dlang.org as well? It could fit under Contribute, or maybe a separate section closer to the top. Ivan Kazmenko.
Re: 111
On Sunday, 21 February 2016 at 12:35:31 UTC, Lisa wrote: ... Is there smth wrong again? Yes. As a programmer, most of the time, you will have to try your programs by yourself before you consider them correct. Now, run a compiler, and it complains: - main.d(20): Error: cannot return non-void from void function - Line 20 of your program is "return 0;", and the void function in question is "void main() {...}". So, you have to fix either of that: make main return int instead of void, or remove the return line. After that, the program will finally compile. But that's not the end, you have to try running it. "Enter side A:" shall we say, "1" and then it writes "Enter side B:" and fails: - std.conv.ConvException@c:\Tools\dmd\windows\bin\..\..\src\phobos\std\conv.d(2729): no digits seen 0x0040666A in ... - That's a whole lot of unfriendly error text on the screen, but the human-readable part is "no digits seen" when reading variable B. Now, read the chapter of Ali's book again very carefully, or one of the posts here. You may then notice that the space inside the quotes is important, and also learn why. The bottom line: the task of writing a program is not finished until you can compile it, run it, give it at least a few example inputs, and it prints the right output for all these inputs. Ivan Kazmenko.
Re: 111
On Saturday, 20 February 2016 at 04:15:50 UTC, Lisa wrote: module main; import std.stdio; import std.math; int main() { int A, B, C; writef("A = "); readf("%lf", %A); writef("B = "); readf("%lf", %B); writef("C1= "); readf("%lf", %C); writefl("P = (%lf)", A + B + C); return 0; } It whatever doesn't work The line "int A, B, C;" should be "double A, B, C;" if you want to be able to operate non-integer lengths as well. The lines like "readf("%lf", %A);" should be "readf(" %s", );". Please read the reasoning again carefully in Ali's book: http://ddili.org/ders/d.en/input.html. The " %s" can be " %f" but not " %lf" (that would be the correct string for C's printf but not for D's readf), and the leading space is important. On the output line, you perhaps meant "writefln" instead of "writefl". Again, "%lf" should be changed into "%f" or "%s".
Re: 111
On Friday, 19 February 2016 at 23:56:29 UTC, Lisa wrote: Can you please help me and explain how to create a program, which would find area of triangle and its perimeter? First, one can't find these unless something is given. So, what is given: sides? angles? two-dimensional coordinates? The next stop is Google for how to do that mathematically, without touching the keyboard. Once you have the above, you may have some specific difficulty expressing that in a programming language of your choice, one which Google (again) can't resolve in a few minutes. If that is the case, please state that difficulty.
Re: Idempotent partition around median of 5?
On Saturday, 6 February 2016 at 00:59:17 UTC, Andrei Alexandrescu wrote: On 02/05/2016 06:36 AM, Ivan Kazmenko wrote: Another interesting task would be to make the function stable, but I don't see how it is possible with such flat structure. Under what circumstances isn't your function unstable? -- Andrei For example, if elements are "value | id", compared by value, then: 0|0, 0|1, 1|2, 0|3, 0|4 is transformed into 0|0, 0|1, 0|4, 0|3, 1|2 and 0|4 is now placed earlier than 0|3, which violates the stability requirement. Things can be reordered a bit, but it seems that no possible order eliminates the need to remember a part of the history. On the other hand, when we track our whole path in the decision tree (e.g. at the leaves of Timon Gehr's tree of ifs), we have all information to make the partition stable. In any case, finding the shortest-code stable partition-of-5 algorithm looks like a problem solvable by an automated searcher. Regarding the speed, there are different use cases with different requirements, for example: 1. Primitive types (cheap swap, cheap comparison). 2. Heavy structs A (expensive swap, cheap comparison - e.g., compare one field of primitive type). 3. Heavy structs B (expensive swap, expensive comparison - e.g., call a heavy external function). 4. Heavy classes (cheap swap - pointers only, expensive comparison). So there's perhaps no single best solution.
Re: Idempotent partition around median of 5?
On Saturday, 6 February 2016 at 07:06:27 UTC, Ivan Kazmenko wrote: On Saturday, 6 February 2016 at 00:59:17 UTC, Andrei Alexandrescu wrote: On 02/05/2016 06:36 AM, Ivan Kazmenko wrote: Another interesting task would be to make the function stable, but I don't see how it is possible with such flat structure. Under what circumstances isn't your function unstable? -- Andrei The code I used to check stability: http://dpaste.dzfl.pl/2b950cb3e5d8 The "y" and "n" at end of lines are "yes"/"no", as in "stable"/"unstable".
Re: Idempotent partition around median of 5?
On Thursday, 4 February 2016 at 01:24:15 UTC, Andrei Alexandrescu wrote: So there's got to be a better solution. Your challenge - should you choose to accept it :o) - is an algorithm that does the partitioning in 6 comparisons and <= 9 swaps, which is idempotent: when applied twice, it always does 0 swaps. Here's my take at it. It's idempotent and does exactly 6 comparisons and 0-8 swaps. The advantages to counter the not-so-good stats are that it has a flat structure, and is not hard to reason about. The idea is to process the following steps: 1. Find the minimum of {b, c, d, e} in three comparisons, and put it into b. The structure is: b < d, c < e, b < c. Note that d and e were not compared if no swaps were made. 2. Find the minimum of {a, c, d, e} in two more comparisons, and put it into a. The structure is: a < d, c < e, a < c. Note that a and b were not compared if no swaps were made. 3. Find the minimum of {c, d, e} in one more comparison, and put it into c. The structure is: c < d, c < e. Note that d and e were not compared if no swaps were made. In the end, we have a < c, b < c, c < d, c < e. Additionally, if these inequalities held initially, everything is left in place regardless of the results of comparisons of (a, b) and (d, e). In code: - import std.algorithm; import std.exception; import std.range; import std.stdio; void p5 (ref int a, ref int b, ref int c, ref int d, ref int e) { if (d < b) {swap (b, d);} if (e < c) {swap (c, e);} if (c < b) {swap (b, c); swap (d, e);} if (d < a) {swap (a, d);} if (c < a) {swap (a, c); swap (d, e);} if (d < c) {swap (c, d);} } void main () { auto a = 5.iota.array; do { auto b = a.dup; p5 (b[0], b[1], b[2], b[3], b[4]); auto c = b.dup; p5 (c[0], c[1], c[2], c[3], c[4]); writeln (a, " -> ", b, " -> ", c); enforce (b[0] < b[2] && b[1] < b[2] && b[2] < b[3] && b[2] < b[4]); enforce (equal (b, c)); } while (nextPermutation (a)); } - Another interesting task would be to make the function stable, but I don't see how it is possible with such flat structure. Ivan Kazmenko.