Случайно услышал рассказ одного коллеги другому о том, что в скриптовых языках все очень клево и удобно. Рассказчик пропагандировал perl, как что-то очень крутое, простое и понятное.
Не удержался и встрял, сказав, что python попонятнее будет, а возможностей предоставляет совсем не меньше.
Дальше меня спросили, как в python обстоят дела с регулярными выражениями, и в результате пришли мы к такой задаче:
Есть строка, необходимо вывести все слова в ней, которые встречаются N раз.
Задачка конечно совсем тривиальная и написание решения занимает считаные минуты, но этот тупняк поглотил всех как минимум на несколько часов. Если вы поддаетесь тупнячкам, то прошу пожаловать подкат
Вот какие решения были:
test1.py написание 3 мин. «war and peace» это решение не осилило
#!/usr/bin/env python
import re
n = 5
with open("./input_file.txt", "r") as f:
s = f.read()
l = re.findall(r'w+',s)
print repr([x for x in l if l.count(x) == n])
test2.pl написание 30 мин (почему то человек выткал долго). время работы на «war and peace»: 0m0.282s
#!/usr/bin/perl
open FH, "<input_file.txt";
local $/;
$str = <FH>;
$n = 5;
%h = ();
$h{$1}++ while $str =~ /(w+)/g;
print '['.(join ", ", grep {$h{$_} == 5} keys %h).']';
время работы первого решения не удовлетворило совсем, поэтому было написано вот это:
test3.py написание 3 мин. время работы на «war and peace»: 0m0.285s
#!/usr/bin/env python
import re
n = 5
with open("./input_file.txt", "r") as f:
s = f.read()
d={}
for x in re.findall(r'w+',s):
if x in d:
d[x] += 1
else:
d[x] = 1
print repr([k for k,v in d.items() if v == n])
test4.pl написание 30 мин (опять очень долго). время работы на «war and peace»: 0m0.221s
Но результат увы некорректный
#!/usr/bin/perl
open FH, "<./input_file.txt";
local $/;
$str = <FH>;
$n = 5;
chomp($str);
foreach(split(/ /, $str)){$h{$_}++;}
my $res ="[";
foreach(keys(%h)) {if($h{$_} == $n){$res .= "$_, ";}}
$res .= "]";
print $res;
test5.hs написание 10 мин. время работы на «war and peace»: 0m2.948s
Человек соорудил его, чтобы сказать «а я еще и на хаскеле могу», но результат не впечатлил
import Data.List
import Data.Char
main = interact -- IO
$ unlines -- combine meta-data into string
. map ((n, w) -> if (n == 5) then show w else "")
. sort -- sort meta-data by occurances
. map (s -> (length s, head s)) -- transform to sublist meta-data
. group -- break into sublists of unique words
. sort -- sort words
. words -- break into words
. map (c -> -- simplify chars in input
if isAlpha c
then toLower c
else ' ')
Ну и раз уж так, то и на C++ тоже реализуем
test6.cpp написание 5 мин. время работы на «war and peace»: 0m0.640s
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string>
#include <iostream>
#include <set>
std::multiset<std::string> words;
void prepare() {
char *p = 0;
int err = 1;
while ( 1 == scanf("%as", &p)) {
words.insert(p);
free(p);
}
if (errno) {
perror("scanf");
abort();
}
}
void output(int n) {
std::multiset<std::string>::iterator it(words.begin());
std::string out;
for(;it!=words.end(); it = words.upper_bound(*it)) {
if ( words.count(*it) == n )
out.append(" ," + *it);
}
if (out.find(" ,") == 0 )
out.erase(0, 2);
std::cout<<"["<<out<<"]n";
}
int main(int argc, char **argv)
{
prepare();
output(atoi(argv[1]));
return 0;
}
Предлагайте свои решения в комментариях, если вы подвержены тупняку и способны сделать лучше за вменяемое время ;)
этот файл использовался как input_file.txt, это «Война и мир» из библиотеки Гутенберга
Автор: 2r2w