digitalmars.D - Type programming game
- Stefan Koch (18/18) Oct 10 2020 Hi,
- Timon Gehr (28/39) Oct 10 2020 I guess the canonical solution is something like this:
- Stefan Koch (7/36) Oct 10 2020 I am thoroughly impressed.
- Adam D. Ruppe (38/40) Oct 10 2020 Surely you know by now what I'm going to say... just write a
- Stefan Koch (3/43) Oct 10 2020 This is a neat solution.
- Patrick Schluter (3/7) Oct 11 2020 It has only the disadvantage of generating code of a new function
- Basile B. (44/62) Oct 11 2020 fully CTFE + using a map to solve uniquness. Naive, longish, but
- Stefan Koch (50/119) Oct 11 2020 Thanks for attending the game!
- Basile B. (3/7) Oct 11 2020 I haven't seen it directly but in my solution the loop that set
- claptrap (17/31) Oct 12 2020 Maybe this type function version will work
- Stefan Koch (12/47) Oct 13 2020 Thanks for you submission.
- Stefan Koch (37/55) Oct 13 2020 I fixed your version to work around the bugs in type functions.
- claptrap (3/40) Oct 13 2020 Yeah not as concise as it could be, but I assume eventually
- Stefan Koch (2/8) Oct 14 2020 Yes of course.
- Basile B. (3/12) Oct 17 2020 So what's up with the benchmark you mentioned ? With four entries
- Stefan Koch (3/18) Oct 17 2020 Coming up. Fixes to accommodate claptrap's original version have
- Basile B. (4/23) Oct 17 2020 yeah but his version is a TF one BTW. Maybe I missed the point,
- Stefan Koch (3/21) Oct 17 2020 You can propose a version using anything that you think will work.
- Basile B. (7/31) Oct 17 2020 Actually, and even it's sure that TF version will be faster, I
- Stefan Koch (13/22) Oct 27 2020 So it turns out not to be the type-array[idx] in general.
Hi, just now I came up with a nice game. Write a template/function takes a sequence of types, and "returns" a string. Whenever the same type appears twice in the sequence directly after the previous occurrence, append ("double " ~ name_of_type) to the string. Whenever it appears three times, append ("triple " ~ name_of_type). So (int, int, uint, uint, uint) would return "double int triple uint") Or (char, char, wchar, dchar, dchar) would return "double char double dchar" I am looking forward to what you come up with. After a few submissions have been made I will post my type function, which fulfills this task. Have a good day, Stefan
Oct 10 2020
On 11.10.20 01:42, Stefan Koch wrote:Write a template/function takes a sequence of types, and "returns" a string. Whenever the same type appears twice in the sequence directly after the previous occurrence, append ("double " ~ name_of_type) to the string. Whenever it appears three times, append ("triple " ~ name_of_type). So (int, int, uint, uint, uint) would return "double int triple uint") Or (char, char, wchar, dchar, dchar) would return "double char double dchar"I guess the canonical solution is something like this: alias Seq(T...)=T; template Group(T...){ static if(T.length==0) alias Group=Seq!(); else static if(T.length==1) alias Group=Seq!(1,T[0]); else{ alias R=Group!(T[1..$]); static if(is(T[0]==R[1])) alias Group=Seq!(R[0]+1,R[1..$]); else alias Group=Seq!(1,T[0],R); } } template solve(T...){ template rec(G...){ static if(G.length==0) enum rec=""; else{ enum r=rec!(G[2..$]); enum s=G[1].stringof~(r.length?" ":"")~r; static if(G[0]==2) enum rec="double "~s; else static if(G[0]==3) enum rec="triple "~s; else enum rec=r; } } alias solve=rec!(Group!T); } static assert(solve!(int,int,uint,uint,uint)=="double int triple uint"); static assert(solve!(char,char,wchar,dchar,dchar)=="double char double dchar");
Oct 10 2020
On Sunday, 11 October 2020 at 00:47:26 UTC, Timon Gehr wrote:I guess the canonical solution is something like this: alias Seq(T...)=T; template Group(T...){ static if(T.length==0) alias Group=Seq!(); else static if(T.length==1) alias Group=Seq!(1,T[0]); else{ alias R=Group!(T[1..$]); static if(is(T[0]==R[1])) alias Group=Seq!(R[0]+1,R[1..$]); else alias Group=Seq!(1,T[0],R); } } template solve(T...){ template rec(G...){ static if(G.length==0) enum rec=""; else{ enum r=rec!(G[2..$]); enum s=G[1].stringof~(r.length?" ":"")~r; static if(G[0]==2) enum rec="double "~s; else static if(G[0]==3) enum rec="triple "~s; else enum rec=r; } } alias solve=rec!(Group!T); } static assert(solve!(int,int,uint,uint,uint)=="double int triple uint"); static assert(solve!(char,char,wchar,dchar,dchar)=="double char double dchar");I am thoroughly impressed. ... also I found a bug in the type-function implementation which will integer-promote the type char into int ... and therefore fail the testcases I set myself. The type-function solution will come tomorrow (since I don't post code that doesn't actually run).
Oct 10 2020
On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan Koch wrote:After a few submissions have been made I will post my type function, which fulfills this task.Surely you know by now what I'm going to say... just write a normal function. module typegame.solution; string easy(T...)() { string result; // I separate out the display name from the seen name // since you might pass a.Foo and b.Foo and want it // differentiated in comparison but both displayed "Foo" string lastDisplay; string lastSeen; int repetitionCount; void finish() { if(repetitionCount != 2 && repetitionCount != 3) return; if(result.length) result ~= " "; if(repetitionCount == 2) result ~= "double "; else result ~= "triple "; result ~= lastDisplay; } foreach(t; T) { if(t.mangleof == lastSeen) { repetitionCount++; } else { finish(); lastSeen = t.mangleof; lastDisplay = t.stringof; repetitionCount = 1; } } finish(); return result; } pragma(msg, easy!(int, int, uint, uint, uint)); pragma(msg, easy!(char, char, wchar, dchar, dchar));
Oct 10 2020
On Sunday, 11 October 2020 at 01:08:46 UTC, Adam D. Ruppe wrote:On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan Koch wrote:This is a neat solution. Congratulations Adam.After a few submissions have been made I will post my type function, which fulfills this task.Surely you know by now what I'm going to say... just write a normal function. module typegame.solution; string easy(T...)() { string result; // I separate out the display name from the seen name // since you might pass a.Foo and b.Foo and want it // differentiated in comparison but both displayed "Foo" string lastDisplay; string lastSeen; int repetitionCount; void finish() { if(repetitionCount != 2 && repetitionCount != 3) return; if(result.length) result ~= " "; if(repetitionCount == 2) result ~= "double "; else result ~= "triple "; result ~= lastDisplay; } foreach(t; T) { if(t.mangleof == lastSeen) { repetitionCount++; } else { finish(); lastSeen = t.mangleof; lastDisplay = t.stringof; repetitionCount = 1; } } finish(); return result; } pragma(msg, easy!(int, int, uint, uint, uint)); pragma(msg, easy!(char, char, wchar, dchar, dchar));
Oct 10 2020
On Sunday, 11 October 2020 at 01:16:29 UTC, Stefan Koch wrote:On Sunday, 11 October 2020 at 01:08:46 UTC, Adam D. Ruppe wrote:It has only the disadvantage of generating code of a new function for each instanciation, does it not?[...]This is a neat solution. Congratulations Adam.
Oct 11 2020
On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan Koch wrote:Hi, just now I came up with a nice game. Write a template/function takes a sequence of types, and "returns" a string. Whenever the same type appears twice in the sequence directly after the previous occurrence, append ("double " ~ name_of_type) to the string. Whenever it appears three times, append ("triple " ~ name_of_type). So (int, int, uint, uint, uint) would return "double int triple uint") Or (char, char, wchar, dchar, dchar) would return "double char double dchar" I am looking forward to what you come up with. After a few submissions have been made I will post my type function, which fulfills this task. Have a good day, Stefanfully CTFE + using a map to solve uniquness. Naive, longish, but easy to understand I'd say as self-criticism... but I suppose that the final goal of this game is to show us an astonishing TF solution ;) --- import std.algorithm; string solveByMapping(T...)() { string[] uniques; size_t[] indexes; size_t[] count; string result; static foreach (TT; T) { if (!uniques.canFind(TT.stringof)) uniques ~= TT.stringof; indexes ~= uniques.length - 1; } count.length = uniques.length; static foreach (i, TT; T) { count[indexes[i]] += 1; } foreach(ref c; count) { if (c != 2 && c != 3) c = 0; } foreach(i, c; count) { if (!c) continue; result ~= (c == 3) ? " triple " : " twice "; result ~= uniques[i]; } return result[1..$]; } static assert (solveByMapping!(int, int, uint, uint, uint) == "twice int triple uint"); static assert (solveByMapping!(int, int, uint) == "twice int"); static assert (solveByMapping!(float, float, int, int, uint) == "twice float twice int"); ---
Oct 11 2020
On Sunday, 11 October 2020 at 09:31:43 UTC, Basile B. wrote:On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan Koch wrote:Thanks for attending the game! And you are right the type function version which works now looks like this. It should not be astonishing ;) --- alias type = __type; string double_triple(type[] types...) { string result; type current; uint count; foreach(i, t;types) { if (is(current == t)) { count++; // if the last one didn't change we need to eval the count if (i == types.length - 1) goto Leval_count; } else { Leval_count: if (count == 2) { result ~= "double " ~ __traits(identifier, current) ~ " "; } else if (count == 3) { result ~= "triple " ~ __traits(identifier, current) ~ " "; } current = t; count = 1; } } return result[0 .. $-1]; } static assert(double_triple(int,int,uint,uint,uint) == "double int triple uint"); static assert(double_triple(char,char,wchar,dchar,dchar) == "double char double dchar"); static assert(double_triple(double, double, float, float, float) == "double double triple float"); --- In continuation I will post benchmarks of all 4 (or more of others come in) solutions on longer type sequences.Hi, just now I came up with a nice game. Write a template/function takes a sequence of types, and "returns" a string. Whenever the same type appears twice in the sequence directly after the previous occurrence, append ("double " ~ name_of_type) to the string. Whenever it appears three times, append ("triple " ~ name_of_type). So (int, int, uint, uint, uint) would return "double int triple uint") Or (char, char, wchar, dchar, dchar) would return "double char double dchar" I am looking forward to what you come up with. After a few submissions have been made I will post my type function, which fulfills this task. Have a good day, Stefanfully CTFE + using a map to solve uniquness. Naive, longish, but easy to understand I'd say as self-criticism... but I suppose that the final goal of this game is to show us an astonishing TF solution ;) --- import std.algorithm; string solveByMapping(T...)() { string[] uniques; size_t[] indexes; size_t[] count; string result; static foreach (TT; T) { if (!uniques.canFind(TT.stringof)) uniques ~= TT.stringof; indexes ~= uniques.length - 1; } count.length = uniques.length; static foreach (i, TT; T) { count[indexes[i]] += 1; } foreach(ref c; count) { if (c != 2 && c != 3) c = 0; } foreach(i, c; count) { if (!c) continue; result ~= (c == 3) ? " triple " : " twice "; result ~= uniques[i]; } return result[1..$]; } static assert (solveByMapping!(int, int, uint, uint, uint) == "twice int triple uint"); static assert (solveByMapping!(int, int, uint) == "twice int"); static assert (solveByMapping!(float, float, int, int, uint) == "twice float twice int"); ---
Oct 11 2020
On Sunday, 11 October 2020 at 10:46:00 UTC, Stefan Koch wrote:On Sunday, 11 October 2020 at 09:31:43 UTC, Basile B. wrote:I haven't seen it directly but in my solution the loop that set `c` to `0` can be removed.On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan KochIn continuation I will post benchmarks of all 4 (or more of others come in) solutions on longer type sequences.
Oct 11 2020
On Sunday, 11 October 2020 at 10:46:00 UTC, Stefan Koch wrote:On Sunday, 11 October 2020 at 09:31:43 UTC, Basile B. wrote:Maybe this type function version will work string double_triple(type[] types...) { string result; uint subidx = 0; foreach(i, t; types) { if ((i == types.length-1) || is(types[i] != types[i+1])) { result ~= ["","double","triple","quadruple"][i-subidx] ~ __traits(identifier, t) ~ " "; subidx = i+1; } } return result; }On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan Koch wrote:static assert(double_triple(int,int,uint,uint,uint) == "double int triple uint"); static assert(double_triple(char,char,wchar,dchar,dchar) == "double char double dchar"); static assert(double_triple(double, double, float, float, float) == "double double triple float"); --- In continuation I will post benchmarks of all 4 (or more of others come in) solutions on longer type sequences.Hi,
Oct 12 2020
On Monday, 12 October 2020 at 14:04:56 UTC, claptrap wrote:On Sunday, 11 October 2020 at 10:46:00 UTC, Stefan Koch wrote:Thanks for you submission. You helped me to find a bug within the TF implementation. For some reason indexing of types[] that does not happen automatically in the foreach doesn't work. (Which is really strange because under the hood it should use the same code...) There is one mistake in your code which I would like to correct. is-expressions cannot use != you have to state it as:On Sunday, 11 October 2020 at 09:31:43 UTC, Basile B. wrote:Maybe this type function version will work string double_triple(type[] types...) { string result; uint subidx = 0; foreach(i, t; types) { if ((i == types.length-1) || is(types[i] != types[i+1])) { result ~= ["","double","triple","quadruple"][i-subidx] ~ __traits(identifier, t) ~ " "; subidx = i+1; } } return result; }On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan Koch wrote:static assert(double_triple(int,int,uint,uint,uint) == "double int triple uint"); static assert(double_triple(char,char,wchar,dchar,dchar) == "double char double dchar"); static assert(double_triple(double, double, float, float, float) == "double double triple float"); --- In continuation I will post benchmarks of all 4 (or more of others come in) solutions on longer type sequences.Hi,(!is(types[i] == types[i+1]))Other than that the code should run well, as soon as the bug with the indexing of __type arrays is fixed.
Oct 13 2020
On Monday, 12 October 2020 at 14:04:56 UTC, claptrap wrote:Maybe this type function version will work string double_triple(type[] types...) { string result; uint subidx = 0; foreach(i, t; types) { if ((i == types.length-1) || is(types[i] != types[i+1])) { result ~= ["","double","triple","quadruple"][i-subidx] ~ __traits(identifier, t) ~ " "; subidx = i+1; } } return result; }I fixed your version to work around the bugs in type functions. (As of git commit 1652c194870f9c66161888425a9cdf01db8187f6 (in https://github.com/UplinkCoder/dmd/tree/talias_master)) Here is it fixed: --- alias type = __type; string double_triple(type[] types...) { string result; size_t subidx = 0; foreach(i, t; types) { // for some reason using type[idx] will only work within an assign exp // this still to be fixed auto t2 = (i == types.length-1) ? cast(type)type.init : types[i+1]; if (!is(t2 == t)) // this works because if t2 is type.init it will eval to false; { if (i-subidx) { result ~= ["","double","triple","quadruple"][i-subidx] ~ " " ~ __traits(identifier, t) ~ " "; } subidx = i+1; } } return result[0 .. $-1]; } static assert(double_triple(char,char,wchar,dchar,dchar) == "double char double dchar"); static assert(double_triple(char,char,wchar,dchar,dchar, dchar) == "double char triple dchar"); ---
Oct 13 2020
On Tuesday, 13 October 2020 at 14:43:23 UTC, Stefan Koch wrote:On Monday, 12 October 2020 at 14:04:56 UTC, claptrap wrote: I fixed your version to work around the bugs in type functions. (As of git commit 1652c194870f9c66161888425a9cdf01db8187f6 (in https://github.com/UplinkCoder/dmd/tree/talias_master)) Here is it fixed: --- alias type = __type; string double_triple(type[] types...) { string result; size_t subidx = 0; foreach(i, t; types) { // for some reason using type[idx] will only work within an assign exp // this still to be fixed auto t2 = (i == types.length-1) ? cast(type)type.init : types[i+1]; if (!is(t2 == t)) // this works because if t2 is type.init it will eval to false; { if (i-subidx) { result ~= ["","double","triple","quadruple"][i-subidx] ~ " " ~ __traits(identifier, t) ~ " "; } subidx = i+1; } } return result[0 .. $-1]; } static assert(double_triple(char,char,wchar,dchar,dchar) == "double char double dchar"); static assert(double_triple(char,char,wchar,dchar,dchar, dchar) == "double char triple dchar"); ---Yeah not as concise as it could be, but I assume eventually type[idx] will work outside assign expressions?
Oct 13 2020
On Wednesday, 14 October 2020 at 00:11:37 UTC, claptrap wrote:On Tuesday, 13 October 2020 at 14:43:23 UTC, Stefan Koch wrote:Yes of course.On Monday, 12 October 2020 at 14:04:56 UTC, claptrap wrote: I fixed your version to work around the bugs in type functions. [...]Yeah not as concise as it could be, but I assume eventually type[idx] will work outside assign expressions?
Oct 14 2020
On Wednesday, 14 October 2020 at 11:14:34 UTC, Stefan Koch wrote:On Wednesday, 14 October 2020 at 00:11:37 UTC, claptrap wrote:So what's up with the benchmark you mentioned ? With four entries + your TF version we can have a podium now.On Tuesday, 13 October 2020 at 14:43:23 UTC, Stefan Koch wrote:Yes of course.On Monday, 12 October 2020 at 14:04:56 UTC, claptrap wrote: I fixed your version to work around the bugs in type functions. [...]Yeah not as concise as it could be, but I assume eventually type[idx] will work outside assign expressions?
Oct 17 2020
On Saturday, 17 October 2020 at 12:46:44 UTC, Basile B. wrote:On Wednesday, 14 October 2020 at 11:14:34 UTC, Stefan Koch wrote:Coming up. Fixes to accommodate claptrap's original version have to be made first.On Wednesday, 14 October 2020 at 00:11:37 UTC, claptrap wrote:So what's up with the benchmark you mentioned ? With four entries + your TF version we can have a podium now.On Tuesday, 13 October 2020 at 14:43:23 UTC, Stefan Koch wrote:Yes of course.On Monday, 12 October 2020 at 14:04:56 UTC, claptrap wrote: I fixed your version to work around the bugs in type functions. [...]Yeah not as concise as it could be, but I assume eventually type[idx] will work outside assign expressions?
Oct 17 2020
On Saturday, 17 October 2020 at 12:53:44 UTC, Stefan Koch wrote:On Saturday, 17 October 2020 at 12:46:44 UTC, Basile B. wrote:yeah but his version is a TF one BTW. Maybe I missed the point, weren't we supposed to propose a version based on CTFE+template only ?On Wednesday, 14 October 2020 at 11:14:34 UTC, Stefan Koch wrote:Coming up. Fixes to accommodate claptrap's original version have to be made first.On Wednesday, 14 October 2020 at 00:11:37 UTC, claptrap wrote:So what's up with the benchmark you mentioned ? With four entries + your TF version we can have a podium now.On Tuesday, 13 October 2020 at 14:43:23 UTC, Stefan Koch wrote:Yes of course.On Monday, 12 October 2020 at 14:04:56 UTC, claptrap wrote: I fixed your version to work around the bugs in type functions. [...]Yeah not as concise as it could be, but I assume eventually type[idx] will work outside assign expressions?
Oct 17 2020
On Saturday, 17 October 2020 at 12:59:19 UTC, Basile B. wrote:On Saturday, 17 October 2020 at 12:53:44 UTC, Stefan Koch wrote:You can propose a version using anything that you think will work. As long as I can get a version of DMD that can compile it.On Saturday, 17 October 2020 at 12:46:44 UTC, Basile B. wrote:yeah but his version is a TF one BTW. Maybe I missed the point, weren't we supposed to propose a version based on CTFE+template only ?On Wednesday, 14 October 2020 at 11:14:34 UTC, Stefan Koch wrote:Coming up. Fixes to accommodate claptrap's original version have to be made first.On Wednesday, 14 October 2020 at 00:11:37 UTC, claptrap wrote:So what's up with the benchmark you mentioned ? With four entries + your TF version we can have a podium now.[...]Yes of course.
Oct 17 2020
On Saturday, 17 October 2020 at 13:37:20 UTC, Stefan Koch wrote:On Saturday, 17 October 2020 at 12:59:19 UTC, Basile B. wrote:Actually, and even it's sure that TF version will be faster, I could propose a second version of my entry since the bounds of the dynamic array I use are tied to the length of the variadic template arg... So I can use static arrays and a variable to give the upper bound in the array of unique types. Not sure if it is worth ;)On Saturday, 17 October 2020 at 12:53:44 UTC, Stefan Koch wrote:You can propose a version using anything that you think will work. As long as I can get a version of DMD that can compile it.On Saturday, 17 October 2020 at 12:46:44 UTC, Basile B. wrote:yeah but his version is a TF one BTW. Maybe I missed the point, weren't we supposed to propose a version based on CTFE+template only ?On Wednesday, 14 October 2020 at 11:14:34 UTC, Stefan Koch wrote:Coming up. Fixes to accommodate claptrap's original version have to be made first.On Wednesday, 14 October 2020 at 00:11:37 UTC, claptrap wrote:So what's up with the benchmark you mentioned ? With four entries + your TF version we can have a podium now.[...]Yes of course.
Oct 17 2020
On Wednesday, 14 October 2020 at 11:14:34 UTC, Stefan Koch wrote:On Wednesday, 14 October 2020 at 00:11:37 UTC, claptrap wrote:So it turns out not to be the type-array[idx] in general. That works as expected. However when it's used inside an is expression. The is-expression's type gets evaluated _before_ executes the type function ctfe And during that time type-array[idx] is not parsed as variable expression. it's parsed as the type of a static array, and assuming that idx is an enum with numeric values so given enum idx := 6; type-array[6] is the type of static array. I am still thinking about how to fix this.On Tuesday, 13 October 2020 at 14:43:23 UTC, Stefan Koch wrote:Yes of course.On Monday, 12 October 2020 at 14:04:56 UTC, claptrap wrote: I fixed your version to work around the bugs in type functions. [...]Yeah not as concise as it could be, but I assume eventually type[idx] will work outside assign expressions?
Oct 27 2020