| Comments: |
Про combinations не понял: "все слова" - из данных?
Нет, не из данных, а все возможные слова, у которых i-й символ взят из i-го входного слова.
И описание полезной команды :so $VIMRUNTIME/syntax/2html.vim
Присоединяюсь к вопросу по поводу №1 - как определять, что слова кончились и пора печатать ?
поправка в условии, внимание!
![[User Picture]](http://l-userpic.livejournal.com/13052443/2641434) | From: uzbeche 2008-03-13 01:43 pm (UTC)
Re: типа тоже решение :-) | (Link)
|
впрочем, на ввод
a bc de
получаем
{a}{b,c}{d,e}
#!/bin/bash
sed 's/\(.\)/\\\1,/g' |
sed 's/.$/}\\/g' |
sed 's/^/{/g' |
sed 's/^.\(..\)..$/\1\\/g' |
sed 's!^.$! >/dev/null \\!' |
sed '1s/^/echo /' |
bash |
sed 's/ /\n/g'
![[User Picture]](http://l-userpic.livejournal.com/27047248/372009) | From: gianthare 2008-03-16 02:00 pm (UTC)
Что там происходит вообще? | (Link)
|
Сверх того, что с помощью sed генерируется какая-то программа для bash? Хотя можно запустить по частям, конечно
Ну, если втупую, то combinations у меня будет примерно такой (схема, компилятор chicken). Работает, похоже, корректно, но наверняка не самая эффективная реализация :)
А, кстати, вторая задача практически эквивалентна первой :) Дифф к предыдущей реализации такой: - (permute (read-lists-of-chars)))
+ (permute (let ((string (read-line)))
+ (make-list (string-length string)
+ (string->list string)))))
![[User Picture]](http://l-userpic.livejournal.com/30812000/4089560) | From: _navi_ 2008-03-13 08:08 pm (UTC)
Первая (Haskell) | (Link)
|
Если немного пренебречь правилами и считать, что слова разделяются пробелами, то так:
fmap (unwords . foldM (map . flip (:)) [] . reverse . words) getLine >>= putStrLn
Если быть честным, то как-то так:
import Control.Monad
combinations = foldM (map . flip (:)) [] . reverse
main = fmap (unlines . combinations . lines) getContents >>= putStr
![[User Picture]](http://l-userpic.livejournal.com/37473381/6423202) | From: migmit 2008-03-16 08:51 pm (UTC)
Re: Первая (Haskell) | (Link)
|
Я тя умоляю. combinations = sequence
![[User Picture]](http://l-userpic.livejournal.com/30812000/4089560) | From: _navi_ 2008-03-13 09:00 pm (UTC)
rant и вторая (Haskell) | (Link)
|
Слова на входе и на выходе оканчиваются переводом строки, этот символ не является частью слова.
Я вот эту фразу по-разному могу понять: либо каждое слово оканчивается переводом строки, либо, как во втором примере, слова разделяются пробелами, а после уже перевод строки. Хотя, вообще говоря, так жёстко описывать формат входных/выходных данных мне не очень нравится: суть задач врядли состоит в том, чтобы прочитать несколько по-особенному разделённых слов и как-то по-особенному же их вывести, к тому же хорошо это специфицировать не так просто. Ясно, что и это надо уметь, но так от главного отвлекаешься на попытки расшифровать, что же имелось в виду.
Вторую особо красиво не получилось написать, ну да я не заморачивался. С эффективностью: надо думать, можно ли сильно лучше.
permutations xs = permutations' [] xs
where
permutations' [] [] = [[]]
permutations' _ [] = []
permutations' bs (x:xs) = (map (x:) $ permutations (bs ++ xs)) ++ (permutations' (x:bs) xs)
main = fmap (unlines . permutations) getLine >>= putStr
import sys
def func(lis):
a,lis = lis[0],lis[1:]
return ["".join([i,k]) for i in a for k in func(lis)] if lis else list(a)
if __name__ == "__main__":
print func(sys.argv[1:])
import sys
def func(lis):
return [ i+k for i in lis for k in func(lis.replace(i, ""))] if len(lis) > 1 else lis
if __name__ == "__main__":
print func(sys.argv[1])
во избежание придирок, в первом случае sys.argv[1:] можно заменить на raw_input().split(), во втором sys.argv[1] на raw_input(), грубо говоря.
Если я правильно понял условие задачи, то combinations решается как-то так:
import Control.Monad
combinations = sequence . lines
main = putStr . unlines . combinations =<< getContents
что-то длинновато получилось
insertions x [] = [[x]]
insertions x (y:ys) = (x:y:ys) : map (y:) (insertions x ys)
permutations [] = [[]]
permutations (x:xs) = concatMap (insertions x) (permutations xs)
main = putStr . unlines . permutations =<< getLine
![[User Picture]](http://l-userpic.livejournal.com/60224859/12541508) | From: deni_ok 2008-03-15 07:20 pm (UTC)
Re: permutations | (Link)
|
Та же идея на list comprehension:
splits xs = inits xs `zip` tails xs
permutations [] = [[]]
permutations (x:xs) = [ps ++ x:qs | rs <- permutations xs,
(ps, qs) <- splits rs]
Вроде короче не выходит, ещё и Data.List импортировать надо для inits и tails. Или явно определить
splits [] = [([], [])]
splits xxs@(x:xs) = ([], xxs):[(x:ps, qs) | (ps, qs) <- splits xs]
![[User Picture]](http://l-userpic.livejournal.com/27047248/372009) | From: gianthare 2008-03-16 01:33 pm (UTC)
А я не постесняюсь решения в лоб выложить | (Link)
|
Combinations
#!/usr/bin/perl
while(<>) {
chop;
push @lines,$_;
}
&combine('',@lines);
sub combine {
my $word = shift;
if(0 == scalar(@_)) {
print $word."\n";
return;
}
my $line = shift;
for my $l (split //,$line) {
&combine($word.$l,@_);
}
}
Permutations
#!/usr/bin/perl
$_ = <>;
chop;
my @word = split //,$_;
print STDERR "Permuting @word\n";
&perm('',@word);
sub perm {
my $cur = shift;
my @word = @_;
if(0 == scalar(@word)) {
print $cur."\n";
return;
}
for(my $i = 0; $i <= $#word; $i++) {
my $t = $word[$i];
$word[$i] = $word[0];
$word[0] = $t;
&perm($cur.$word[0],@word[1..$#word]);
}
}
![[User Picture]](http://l-userpic.livejournal.com/27047248/372009) | From: gianthare 2008-03-16 03:02 pm (UTC)
А вот комбинации stripped down to the bones, тскзть | (Link)
|
#!/usr/bin/perl sub combine { $#_? do { combine($_[0].$_,@_[2..$#_]) for @{$_[1]}; } : print $_[0]."\n"; } combine('',map {chop; [split //];} (<>));
По непонятности и краткости уже может конкурировать с Хаскелем, по-моему
#include <cstdio>
#define swap(k,i) {int tmp=a[k]; a[k]=a[i]; a[i] = tmp;}
char a[101] ;
int N = 0;
void shuffle(int k)
{
if(k<N-1)
for(int i=k; i<N; ++i)
{
swap(k, i) ;
shuffle(k+1) ;
swap(k, i) ;
}
else
printf("%s\n", a) ;
}
int main()
{
for(int ch ; (ch=getchar())!=EOF && ch!='\n'; ++N)
a[N] = ch ;
a[N] = '\0' ;
if(N<=1)
printf("%s\n", a) ;
else
shuffle(0) ;
return 0 ;
}
![[User Picture]](http://l-userpic.livejournal.com/27047248/372009) | From: gianthare 2008-03-16 03:04 pm (UTC)
Как же shuffle, когда permute | (Link)
|
Кстати, насколько я помню, должно работать и без второго swap. А отдельная обработка единичной длины действительно необходима?
NB. Наверняка можно и короче, но для этого надо думать :) permuts =. 3 : '((i.@! A. i.) # y.) { y.'
------------------------------------------
Результат работы permuts 'abc' abc acb bac bca cab cba
А по первой части пока не вкурил условие, буду думать.
О! А вот и APL. Только придется вам объяснить, что здесь делается, а то, боюсь, J мало кто читает
Про перестановки: требование уникальности необязательно - алгоритм Кнута (доступный в С++ как std::next_permutation()) корректно переставляет и с дубликатами.
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string word;
cin >> word;
sort(word.begin(), word.end());
do
{
cout << word;
}
while(next_permutation(word.begin(), word.end());
}
Комбинации: то есть, нужно построить декартово произведение. P = S 1*S 2*...*S nP k = S k*S k+1...*S nP k = S k*P k+1Здесь слева от * - множество символов, а справа - множество векторов. Традиционно для хаскела, и множества, и векторы представлены списками. Произведение выглядит так
mult cs vs = [ c:v | c<-cs, v<-vs ] -- для каждого символа и каждого вектора выполнить конкатенацию
Любители могут выразить это через монадные комбинаторы. Ну а произведение всех множеств - это, очевидно свёртка их списка.
combinations ws = foldr mult [[]] ws
Единственная хитрость - нуль-произведение - это не пустое множество, а множество из единственного нульмерного вектора. Теперь только осталось присобачить ко вводу-выводу. | |