Odtwórz zdanie ponownie

12

To wyzwanie składa się z dwóch części. Zwycięzcą zostanie rozwiązanie o najniższej całkowitej liczbie bajtów. Do obu wyzwań należy użyć tego samego języka.

Część 1:

Napisz funkcję lub program, który pobiera zdanie zawierające tylko poprawne słowa jako dane wejściowe i wyświetla listę używanych znaków, liczbę przypadków użycia każdej litery oraz liczbę liter w każdym ze słów w oryginalnym zdaniu. Dane wyjściowe z tego programu muszą być poprawnymi danymi wejściowymi do następnego programu (dokładnie tak, jak są wysyłane)

W dalszej części dodam przykłady i szczegółowe zasady.

Część 2:

Napisz funkcję lub program, który pobiera dane wyjściowe z pierwszego programu jako dane wejściowe i wykorzystuje tę listę angielskich słów i odtwarza zdanie z informacjami z danych wyjściowych. Zdanie nie musi być takie samo jak zdanie oryginalne.

Więcej informacji. zasady i ograniczenia:

Część 1:

  • Pierwsze wejście może być w dowolnym odpowiednim formacie, ze znakami cudzysłowu lub bez, jako argument funkcji lub ze STDIN, z nawiasami lub bez itp.
  • Zdanie wejściowe nie będzie zawierało znaków interpunkcyjnych ani specjalnych, z wyjątkiem kropki / kropki na końcu. Z wyjątkiem symbolu kropki wszystkie znaki na wejściu będą na liście słów.
  • Pierwsza litera zdania będzie pisana wielkimi literami, reszta będzie pisana małymi literami.
  • Wyjście z części 2 musi zaczynać się od tej samej wielkiej litery, co oryginalne zdanie (więc konwersja tekstu na małe nie jest zalecana (ale OK).
  • Dane wyjściowe mogą być w dowolnym odpowiednim formacie:
    • Musi istnieć możliwość skopiowania i wklejenia wyjścia bezpośrednio do następnego programu / funkcji
    • Podczas wklejania kopii nie można wprowadzać żadnych zmian, całe wyniki należy skopiować i wkleić jako całość, a nie w częściach.
    • Możesz na przykład wypisać histogram wszystkich liter w alfabecie lub tylko tych, które zostały użyte (ogólnie wszystko, co jest konieczne do wypełnienia części 2)
    • Nie można wypisać listy znaków, w których powtarzanych jest wiele wystąpień. Na przykład, The queuenie może dać wyjście: Teeehquu (3,5)powinno być coś takiego: Tehqu, (1 3 1 1 2),(3 5).

Część 2:

  • Program / funkcja musi zaakceptować dane wejściowe dokładnie tak, jak w części 1 (jeden wyjątek, patrz komentarz poniżej dotyczący przyjmowania nazwy pliku jako danych wejściowych.).
    • Jeśli do przeanalizowania danych wejściowych konieczne są otaczające nawiasy kwadratowe, znaki cudzysłowu itp., Muszą one stanowić część wyniku z części 1.
  • Lista słów znajduje się tutaj.
    • Listę słów można zapisać lokalnie jako w.txtlub pobrać z adresu URL. Adres URL będzie liczył się tylko jako 5 bajtów, więc nie potrzebujesz skracacza adresów URL.
    • Jeśli program nie może otworzyć plik bez czytania nazwy jako dane wejściowe ze standardowego wejścia (wierzę, że to znaczy było w przypadku Pyth co najmniej), a następnie nazwę pliku można traktować jako oddzielną argumentu wejściowego.
  • Wynikiem musi być tylko zdanie (lista prawidłowych słów), kończące się kropką i opcjonalnym znakiem nowej linii.
    • Wynik musi zawierać słowa z taką samą liczbą liter jak oryginalne zdanie w części 1 (w odpowiedniej kolejności)
    • Wszystkie litery użyte w pierwotnym zdaniu muszą zostać użyte w nowym wyjściu.
    • Zdanie musi zaczynać się od tej samej wielkiej litery, co oryginalne zdanie wejściowe i kończyć się kropką.

Obie części:

  • Wykonanie żadnej z części nie powinno zająć więcej niż 2 minuty (losowe wybieranie słów do momentu rozwiązania problemu nie jest akceptowane).

Zgodnie z zasadami wymienionymi powyżej powinna istnieć spora szansa na odtworzenie dokładnie tego samego zdania, jednak nie jest to wymagane.

Przykłady:

W poniższych przykładach pokazano kilka różnych formatów wejściowych i wyjściowych. Wiele innych jest akceptowanych.

Część 1:

Wejście:

Zulus win.

Typ wyjścia 1:

Z i l n s u w
1 1 1 1 1 2 1
5 3

Typ wyjścia 2:

(('Z',1),('i',1),('l',1),('n',1),('s',1),('u',2),('w',1)), (5,2)

Typ wyjścia 3:

'Zilnsuuw',[1,1,1,1,1,2,1],[5,2]

Część 2:

Dane wejściowe: dokładna kopia wyniku z części 1. Dane wyjściowe:

Zulus win.

Zauważ, że inne kombinacje słów są akceptowane, o ile zaczynają się od Z, a pierwsze słowo ma 5 liter, a drugie 3.

Najkrótszy kod w bajtach wygrywa.

Stewie Griffin
źródło
Oto zatwierdzenie: github.com/isaacg1/pyth/commit/…
PurkkaKoodari
@ LegionMammal978: Tak, możesz to zrobić z następującymi ograniczeniami: Dane wyjściowe, f1które zostały wklejone, f2muszą zawierać wszystkie dane określone w wyzwaniu. Żadne dodatkowe dane nie mogą być częścią danych wyjściowych f1. Żadne dane nie mogą być „przechowywane” w celu f1udostępniania informacji podczas ich wywoływania f2. f1może przyjmować tylko jeden ciąg jako dane wejściowe na połączenie.
Stewie Griffin,
1
Wydaje mi się, że szansa na wypowiedzenie tego samego zdania z więcej niż 3 słowami jest dość zła
Eumel
Zasadniczo tak, ale istnieje wiele przypadków, w których możesz uzyskać to samo zdanie. Jeśli twoja babcia ma dość przerabiania starego swetra, może to być: „rezygnacja z przerabiania dziewiarskich”. Nie sprawdziłem, ale wydaje mi się, że twoja babcia nadal rezygnuje po części 2. Również kombinacje dłuższych słów mogą dać to samo zdanie.
Stewie Griffin,
1
@StewieGriffin Możesz łatwo dostać „Peruka ... wow”. wróć z tym przykładowym zdaniem.
question_asker

Odpowiedzi:

5

LabVIEW, 166 Prymitywy LabVIEW

Przede wszystkim nie stworzyłem 2 oddzielnych programów, ponieważ Labview wykonuje przepływ danych, więc naprawdę nie ma takiej potrzeby.

Zapisuje histogram z pierwszym elementem = kod ascii reszty pierwszej litery od 1 do 26 razy według kwoty. Długość zostaje po prostu zapisana w tablicy.

Pierwsze słowo ma 3 czeki, pierwszą literę, długość i dostępne litery w histogramie. Sprawdzanie pierwszej litery zatrzymuje się po pierwszym słowie.

Histogram sprawdzam, zmniejszając go dla każdej litery i sprawdzając, czy spadnie poniżej zera.

Jeśli znalazłem moje n-te słowo i nie ma żadnych słów, które można zbudować z pozostałych liter, zacznę usuwać słowa ze słownika i powtarzać n-te słowo i tak dalej, aż znajdę rozwiązanie.

To może, ale nie musi, zadziałać dla zdań, ponieważ ich obliczenie potrwa wieczność (mój przykład zajął już kilka sekund).

Co próbowałem

In: Zulus win.
Out: Zulus win.

In: Dovecot flagships oleander.
Out: Dolphin advocates forelegs.

In: Abash abel mammal test.
Out: Amass abbe hamlet malt.

Eumel
źródło
3

Python 2.7, 353 bajty

Niestety nie mogę go przetestować z użyciem rzeczywistego bankomatu pliku w.txt, ponieważ wydaje się, że QPython dla systemu Android nie obsługuje plików we / wy. Działa to z danymi, które skopiowałem i wkleiłem.

Część 1, 76 bajtów

h=lambda s:({c:s.count(c)for c in s if c.isalnum()},map(len,s[:-1].split()))

W: 'Hi there.'

Na zewnątrz: {'H':1, 'i':1, 't':1, 'h':1, 'e':2, 'r':1}, (2, 5)

więc lista zawierająca:

  • skrót mapy z histogramem

  • lista listów

Część 2, 277 bajtów

import itertools as i
m=lambda c:' '.join([s for s in i.product(*[[w for w in open('w.txt')if len(w)==length]for length in c[1]])if sorted(''.join(s))==sorted(sum([[k.lower()]*n for k,n in c[0].items()],[]))and s[0][0]==filter(str.isupper,c[0])[0].lower()][0]).capitalize()+'.'

Naprawdę się cieszę, że udało mi się sprawić, aby była w 100% czysta funkcjonalna. Nie jestem pewien, czy to pomaga w prawdziwym golfie, ale z pewnością dobrze zrozumiałem część zaciemniania: D Oto bardziej przyjazna dla człowieka wersja pt. 2 (dokładnie ten sam przepływ, ale z nazwami zmiennych):

from itertools import product

def matching(counts):
  histo, word_lengths = counts
  first_letter = filter(str.isupper, histo)[0].lower()

  letters_nested = [ [char.lower()]*count for char, count in histo.items() ]
  letters = sum(letters_nested, [])

  word_options = [[word for word in open('w.txt') if len(word)==length] for length in word_lengths]

  sentences = product(*word_options)

  valid = [sentence for sentence in sentences if sorted(''.join(sentence))==sorted(letters) and sentence[0][0]==first_letter]
  return ' '.join(valid[0]).capitalize()+'.'
uryga
źródło
3

Perl, 516 504 bajtów

zawiera 2x +1 za -p

@l=map{length}/\w+/g;s/\w/$c{$&}++/eg;@h=map{"$_$c{$_}"}keys%c;$_="@h @l";chomp(@w=`cat w.txt`);s/([A-Z])1//;$o=$1;s/(\w)(\d)/$h{$1}=$2,''/eg;@L=/\d/g;$l=shift@L;@O=$_,s/^.//,g([@L],%h)&&last for grep{$l==length&&/^$o/i&&h(\%h,substr$_,1)}@w;$_="@O.";s/^./uc$&/e;sub g{my%g;($R,%g)=@_;my@R=@$R;if($j=shift@R){s/./$g{$&}--/eg;my@C=grep{$j==length&&h(\%g,$_)}@w;push(@O,$_),g([@R],%g)and return 1 or pop@O for@C;0}else{1}}sub h{($y,$z)=@_;my%T;$z=~s/\w/$T{$&}++/eg;$K=1;$K&=$T{$_}<=$y->{$_}for keys%T;$K}

Wymaga posiadania w.txtw formacie uniksowym ( \nzakończenia linii). Używa catdo odczytu pliku; zmień na typena Windows.
Zapisz oneliner powyżej 534.pli uruchom jako echo Test. | perl -p 534.pl.

Dość duży, ale to początek - wiele okazji do gry w golfa, ale chciałem go opublikować, aby odpowiedź LabVIEW była mniej samotna ;-). Pominąłem optymalizacje do wykonania poniżej sekundy, oszczędzając ponad 30 bajtów.


Pierwszy fragment (73 bajty):

@l=map{length}/\w+/g;s/\w/$c{$&}++/eg;@h=map{"$_$c{$_}"}keys%c;$_="@h @l"

Tworzy histogram i długość słowa w kompaktowym formacie. Dla danych wejściowych Zulus win.generuje wyjście typu 2 bez (,), które nie są tutaj konieczne:

s1 l1 u2 Z1 w1 i1 n1 5 3

Oto nieoszlifowany:

sub i{
    $_=shift;                       # get parameter
    @l = map{length} /\w+/g;        # cound word lengths
    s/\w/$c{$&}++/eg;               # count letters in hash %c
    @h=map{"$_$c{$_}"}keys%c;       # construct letter-frequency pairs
    "@h @l"                         # implicit interpolation with $" (space) separator
}

Drugi fragment (441 bajtów)

Ta główna część dotyczy we / wy i specjalnego traktowania pierwszej litery, przy użyciu podprogramów gi hwymienionych poniżej.

sub o {
    $_=shift;
    chomp(@w=`cat w.txt`);          # load the wordlist.

    s/([A-Z])1//; $o=$1;            # get and remove the uppercase character,
    s/(\w)(\d)/$h{$1}=$2,''/eg;     # reconstruct histogram in hash %h.
    @L=/\d/g;                       # get the word counts.

    $l = shift @L;                  # get the first word length.

    @O = $_,                        # initialize output with first word,
    s/^.//,                         # strip first char of word
    g([@L],%h) && last              # call the main algoritm and quit on success

    for grep {                      
            $l==length &&           # check length
            /^$o/i &&               # only match words starting with the uppercase char
            h(\%h,substr$_,1)       # check if the word satisfies the histogram
        } @w;                       # iterates all words (speedups removed).

    $_="@O.";                       # construct output sentence.
    s/^./uc$&/e;                    # make first char uppercase.
    $_
}

Ta funkcja rekurencyjna pobiera kopię histogramu, kopię pozostałych słów i bieżące słowo. Jeśli tablica długości słowa jest pusta, zwraca wartość true. W przeciwnym razie zmniejsza histogram dla liter w danym słowie, przyjmuje następną długość słowa i znajduje listę odpowiednich słów z listy słów. Dla każdego odpowiedniego słowa powtarza się.

sub g {
    my%g;                           # local version of histogram
    ($R,%g)=@_;                     # get parameters.
    my@R=@$R;                       # dereference arrayref copy of word lengths.

    if($j=shift @R)                 # get the next word-length.
    {
        s/./$g{$&}--/eg;            # update histogram

        my @C =                     # get a list of suitable words.
        grep { $j==length && h(\%g,$_) }
        @w;

        push(@O,$_),                # append word to output
        g( [@R], %g )               # recurse.
            and return 1            # true: append word we're done.
            or pop @O               # remove word from output
        for @C                      # (for some reason the @C=grep doesn't work here)

        ;0
    } else { 1 }                    # no more words, done!
}

I na koniec podprogram ten otrzymuje słowo i histogram zdania. Oblicza nowy histogram dla tego słowa i sprawdza, czy wszystkie litery nie występują częściej niż dopuszcza to histogram zdania.

# check if first histogram is within bounds of second
sub h{
    ($y,$z)=@_;
    my%T; $z =~ s/\w/$T{$&}++/eg;    # calc histogram

    $K=1;
    $K &= $T{$_} <= $y->{$_}
    for keys %T;#$_[0];
    $K
}

Możesz wkleić nieprzypisane fragmenty ( sub i/o/g/h) w jednym pliku i dołączyć poniższy kod testowy.

sub t {
    print $i=i(shift),$/,o($i),$/x2;
    %c=%h=@L=@X=@O=();
}

t "Test.";                              # Test.
t "Zulus win.";                         # Zulus win.
t "Happy solstice.";                    # Happy solstice.
t "Abash abel mammal test.";            # Abase alms embalm that.
t "Dovecot flagships oleander.";        # Dangled horoscope festival.
t 'This code requires further golfing.';# Tech deer fighting ferrous liquors.

  • aktualizacja 504 : zapisz 12 bajtów eliminując a substri parametr dla sub g.
Kenney
źródło
Rozumiem, kradnie moje przykłady! Żartowanie z rasultów jest przezabawne XD
Eumel
@Eumel Tak, były inne niż twoje, więc zawarłem je :-)
Kenney