Thread overview | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 10, 2020 Type programming game | ||||
---|---|---|---|---|
| ||||
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 |
October 11, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | 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"); |
October 11, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | 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).
|
October 11, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | 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));
|
October 11, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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:
>> 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));
This is a neat solution.
Congratulations Adam.
|
October 11, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | 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:
>> [...]
>
> This is a neat solution.
> Congratulations Adam.
It has only the disadvantage of generating code of a new function for each instanciation, does it not?
|
October 11, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | 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, > > Stefan fully 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"); --- |
October 11, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | 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: >> 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 > > fully 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"); > --- 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. |
October 11, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | 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:
>> On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan Koch
> In continuation I will post benchmarks of all 4 (or more of others come in) solutions on longer type sequences.
I haven't seen it directly but in my solution the loop that set `c` to `0` can be removed.
|
October 12, 2020 Re: Type programming game | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | 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: >> On Saturday, 10 October 2020 at 23:42:46 UTC, Stefan Koch wrote: >>> Hi, >>> > 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. 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; } |
Copyright © 1999-2021 by the D Language Foundation