The Expressive C++17 Coding Challenge in D
seb.wilzba.ch
seb.wilzba.ch
I still prefer Rust for many reasons (no exceptions, no GC, memory safety), but in my heart D is the second favourite - the more lightweight, expressive and pragmatic. I especially wish Rust had macro system and compilation times of D because they are the best in the class. :]
I am appalled that a 125-line program to do such a simple job could win. If that was the best they could do, I would have kept the challenge open until something better came in.
I haven't tried the other programs on one-field files, or where the field selected is the first, or the last. Did you?
#include <iostream>
#include <fstream>
#include <streambuf>
#include <algorithm>
#include <string>
int main(int, char** argv) {
std::ifstream in(argv[1]);
std::string head;
if (!(in >> head)) return std::cout << "input file missing\n", 1;
head = "," + head + ",";
auto sub = std::string(argv[3]);
auto target = "," + std::string(argv[2]) + ",";
auto pos = head.find(target);
if (pos == std::string::npos)
return std::cout << "column name doesn’t exists in the input file\n", 1;
auto skip_pre = pos ? std::count(&head[0], &head[pos], ',') : 0;
auto skip_post = std::count(
&head[pos + target.size()], &head[head.size()], ',');
std::ofstream out(argv[4]);
auto ib = in.rdbuf(), ob = out.rdbuf();
ob->sputn(&head[1], head.size()-2); ob->sputc('\n');
bool skipping = pos == 0;
for (int c = 0, count = skip_pre; (c = ib->snextc()) != EOF; ) {
if (c == ',' || c == '\n') {
if (skipping) {
count = skip_post + skip_pre;
skipping = count == 0;
ob->sputn(&sub[0], sub.size());
} else if (--count == 0) {
skipping = true;
}
ob->sputc(c);
} else if (!skipping)
ob->sputc(c);
}
}The goal of that challenge was to pack the most C++17 features in a program, and it was just a challenge organized by a couple of blogs.
The winner was also a self-confessed amateur. That's a telltale sign of how many people have participated, and the level of engagement that the challenge had.
(awk (:inputs *stdin*)
(:set fs "," ofs ",")
(:let pos (name [*args* 0]) (rplc [*args* 1]))
((= nr 1) (set pos (pos name f)))
((> nr 1) (set [f pos] rplc))
(t (prn)))
Missing args -> pass through: $ txr solve.tl < data
name,surname,city,country
Adam,Jones,Manchester,UK
Joe,Doe,Cracow,Poland
Michael,Smith,Paris,France
Alex,McNeil,Gdynia,Poland
With args: $ txr solve.tl city London < data
name,surname,city,country
Adam,Jones,London,UK
Joe,Doe,London,Poland
Michael,Smith,London,France
Alex,McNeil,London,Poland
We need (:inputs stdin) so that awk takes its input from standard input rather than processing the city London arguments as input sources. open Core
let () =
if Array.length Sys.argv <> 5 then
Printf.eprintf "Invalid args\nUsage: %s <input.csv> <column-name> <replacement-string> <output.csv>" Sys.argv.(0)
else
let input_file, column_name, replacement, output_file = Sys.argv.(1), Sys.argv.(2),Sys.argv.(3),Sys.argv.(4) in
In_channel.with_file input_file ~f:(fun in_ch ->
match In_channel.input_line in_ch with
| None -> Printf.eprintf "Cannot read first line"
| Some first_line ->
let columns = String.split first_line ~on:',' in
match List.findi columns ~f:(fun _ col -> col = column_name) with
| None -> Printf.eprintf "Cannot find column: %s" column_name
| Some (index, _) ->
let _ = Out_channel.with_file output_file ~f:(fun out_ch ->
Out_channel.output_string out_ch (first_line ^ "\n");
In_channel.fold_lines in_ch ~init:() ~f:(fun _ line ->
let in_columns = String.split line ~on:',' in
let out_columns = List.mapi ~f:(fun i col -> if i = index then replacement else col) in_columns in
let out_line = (String.concat ~sep:"," out_columns) ^ "\n" in
Out_channel.output_string out_ch out_line
)
) in ())> So the purpose of this challenge is to write a piece of code that contains as many features of C++17 as possible, and that is as clear as possible.
...which, clearly, states that the goal was not minimize lines of code.
I bet D fanboys can find more apples-to-oranges comparisons where D comes out as the most citric alternative when compared with apples and bananas.
And by the way, the contest was organized by a couple of blogs, and the winner was a self-confessed amateur. Hardly a tour de force in C++ programming.
I'd also like to point out that SafeD covers a fair bit of the language. Enough that I feel comfortable making it a requirement in production code.