5 ms·
Would be great if somebody could post Python/Ruby/.. code here that achieves the same, just to compare. Even with all the C++11 additions it never felt like scr
by stinos 13y ago
Would be great if somebody could post Python/Ruby/.. code here that achieves the same, just to compare. Even with all the C++11 additions it never felt like scripting to me, and I use it practically every day.
Small nitpcik to the author: please define variables when you're going to use them, not C-style all at the beginning of the function. It makes code easier to understand. It doesn't make the reader wonder 'hey what's this variable going to be used for' then having to crawl through all code underneath it. It creates code that's easier to refactor. Also, but more arguably for such a small sample: http://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice http://stackoverflow.com/questions/1452721/why-is-using-name...
- danmaz74 13y agoRuby: array = IO.readlines ARGV[0] array.sort! File.write ARGV[1], array.join("\n") edit: get input and output file names from command line
- stinos 13y agoNow that's the succinctness I'd expect from an actual scripting language
- deleted 13y ago[deleted]
- deleted 13y ago[deleted]
- hamidr 13y agoThe thing is in ruby you are already in main method so there's no need to declare main function as an entry point. The main reason that the c++ version the code is longer has some historical/performance related issues! In c++11 it could've been with smaller standard library at design but that could break the old codes! Although obviously, "Little code =! Better code". What you want to achieve is actually more important. Btw, C++ as a scripting language? at first you might think that way but truly that's a big lie :)
- danmaz74 13y agoI'm not arguing with that ;) BTW, I would never use Ruby for anything that needs performance, but for ease of use and readability it's really great.
- ollysb 13y agoIf we want to golf it, it would probably just be lines = IO.readlines ARGV[0] File.write ARGV[1], lines.sort.join('\n') certainly more readable than the C++ even if you're unfamiliar with ruby.
- danmaz74 13y agoWell, if you really want to golf it, you can just write: File.write ARGV[1], IO.readlines(ARGV[0]).sort.join('\n') ;)
- Freaky 13y agoYou're fired. IO.write(ARGV[1], ARGF.lines.sort.join)
- Aaronneyer 13y agoI believe you still need to join on newline, the default is space. However you can save a couple characters by using `$*` instead of ARGV. Also, trim out the space between the arguments and kill the parenthesis for the optimal golfing.
- danmaz74 13y agoWow, this is really sweet and esoteric (didn't know about ARGF) - but, reading the docs for ARGF, wouldn't it also try to ready from ARGV[1]? Maybe this would fix it: IO.write(ARGV.pop, ARGF.lines.sort.join('\n'))
- deleted 13y ago[deleted]
- vjoel 13y agoOr: ruby -e 'puts ARGF.sort' file.txt Also, this reads stdin if the argument is omitted.
- MereInterest 13y agoPython: import sys data = open(sys.argv[1]).readlines() data.sort() open(sys.argv[2],'w').write(''.join(data))
- deleted 13y ago[deleted]
- benhoyt 13y agoNot bad, however with the ''.join(data) you're effectively doubling the amount of memory needed for large files, because it will build the entire output string in memory (and you've already got the list in memory). Better to use writelines(). You can also use sorted() to iterate over and sort the input lines automatically: sorted_lines = sorted(open(sys.argv[1])) open(sys.argv[2]).writelines(sorted_lines)
- deleted 13y ago[deleted]
- z92 13y agoPHP: <? $lines=file($argv[1]); sort($lines); file_put_contents($argv[2],implode("\n",$lines));
- jackmaney 13y agoHere's a Perl example. This isn't optimally compact, but this is more or less how I would write a script like this if I had to put it into production at $work (maybe with an extra check to make sure that exactly two command line arguments were provided). use strict; use warnings; open my $read,"<",$ARGV[0] or die $!; my @lines = <$read>; close $read; open my $write,">",$ARGV[1] or die $!; print $write $line foreach my $line(sort @lines); close $write;
- hsmyers 13y agoIf version >= 5.10 you can drop the 'or die' and for that matter neither of the close statements are necessary(in any recent version).
- prakashk 13y agoPerl5 v12 and up: use v5.12; # enables strictures open my $in, "<", $ARGV[0]; open my $out, ">", $ARGV[1]; print $out sort <$in>; Perl6: sub MAIN( $in, $out ) { spurt( $out, open($in, chomp => False).lines.sort.join ) } [EDIT: fixed typo in first example]
- draegtun 13y agoHere's a couple of interesting Perl alternatives: my @files = map { IO::File->new($_->[0], $_->[1]) || die $! } ([shift, 'r'], [shift, 'w']); $files[1]->print( sort $files[0]->getlines ); $_->close for @files; And... use autodie; open my $out, '>', $ARGV[1]; print {$out} sort do {open my $in, '<', $ARGV[0]; <$in>};
- ctz 13y ago> Would be great if somebody could post Python/Ruby/.. code here that achieves the same, just to compare. It's actually really hard to completely rewrite that program in most scripting languages: they tend not to have the same concept of undefined behaviour. 'sys.argv[2]' in python (with sys.argv = ['thing.py']) is fully defined (raises an IndexError). 'argv[2]' in C++ (with argv = (char*[2]) { "./thing", 0 }) is undefined. If you scripting language has an FFI library (ctypes in python, say) then you could probably do something equivalent.
- stinos 13y agogood point about the UB. Together with shin_lao's comment about the error/exception handling bascially sums up why the author's claim only makes some sense, but not a lot.
- mikeash 13y agoDefined behavior is a subset of undefined behavior. Specifically, "raises an IndexError" is a perfectly legal thing for a C++ implementation to do in this case. Approximately zero real world implementations do this, but nothing says they can't.
- crntaylor 13y agoHaskell: import System.Environment import Data.List main = do infile:outfile:_ <- getArgs input <- readFile infile writeFile outfile . unlines . sort . lines $ input
- dmytrish 13y agoIt's a bit odd way of matching items of a list, I'd prefer to specify it without any possible trailing items: [infile, outfile] <- getArgs Also, the last two lines may be squeezed into one (though less readable): writeFile outfile =<< (unlines . sort . lines) `fmap` readFile infile
- crntaylor 13y agoOn your first point; I was matching the behaviour of the C++ program in the blog post, which allows any number of command line arguments but only uses the first two. On your second point, I actually thought about writing the whole thing as getArgs >>= \a -> readFile (a!!0) >>= writeFile (a!!1) . unlines . sort . lines but decided that that's exactly the kind of thing that gets Haskell programmers a bad reputation.
- nightski 13y agoAgreed, it does and you made the right choice. But in reality once you know Haskell - bind is a very common operation and reading this version is very natural.
- ygra 13y agoPowerShell: function Sort-File ($Path, $Destination) { Get-Content $Path | Sort-Object | Out-File $Destination } Granted, shells are probably at an advantage when it comes to file management. I'd think a bash variant would be quite short as well. Aiming for succinctness by using aliases and using redirection instead of cmdlets for writing the file (shorter, but less flexible): function sf { gc $args[0] | sort > $args[1] } That's not code anyone should write outside code golfing, though ;-)
- deleted 13y ago[deleted]
- MereInterest 13y agoYeah, the bash variant is obscenely short as well. Short enough that it isn't worth having as a separate program. cat in.txt | sort > out.txt
- deleted 13y ago[deleted]
- 1_player 13y agoNo need for cat! sort in.txt > out.txt
- femto 13y agoCurious, in case I'm missing something. Is what you've written equivalent to the following, or is there a reason for the pipe? sort in.txt > out.txt
- MereInterest 13y agoFrom the other comment, it is completely equivalent, and I will admit that the pipe is due purely to my ignorance. I usually use `sort` for sorting the output of other commands, and so I forget that it can open a file on its own.
- 13y ago
- ptx 13y agoPython (assuming that the last line ends with a newline): import sys open(sys.argv[2], "w").writelines(sorted(open(sys.argv[1])))
- rlpb 13y agoUnix shell: sort
- deleted 13y ago[deleted]
- Aaronneyer 13y agolines = File.read(ARGV[0]).lines.sort File.open(ARGV[0]){|f| lines.each{|l| f.puts(l)}}
- lzman 13y ago>Small nitpcik to the author ifile, line and data have to be defined before the loop. ofile could be defined closer to usage, but I think it's much clearer where it is, grouping in and out defs together making it obvious how argv is used for each.
- Vodurden 13y agoAnother way to do it in C++ is: #include <iterator> #include<vector> #include<algorithm> #include<fstream> using namespace std; // Bad but shorter! int main(int argc, char** argv) { ifstream infile(argv[1]); ofstream outfile(argv[2]); ifstream_iterator<string> start(infile), end; vector<string> lines(start, end); sort(lines.begin(), lines.end()); copy(lines.begin(), lines.end(), ostream_iterator<char>(outfile, "\n")); }
- draegtun 13y agoIn Rebol: Rebol [] files: map-each n system/options/args [to-file n] write/lines files/2 sort read/lines files/1