Pull to refresh

Насколько вы подвержены тупняку, и немного holywar

Reading time3 min
Views14K
Случайно услышал рассказ одного коллеги другому о том, что в скриптовых языках все очень клево и удобно. Рассказчик пропагандировал 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, это «Война и мир» из библиотеки Гутенберга
Tags:
Hubs:
+2
Comments94

Articles