Wzajemnie wypełnij puste pola

11

Biorąc pod uwagę wejście dwóch ciągów znaków z sekwencjami znaków podkreślających odpowiadające słowa, wypisz zdania z wypełnionymi „pustymi miejscami”.

Najlepszym sposobem opisania tego wyzwania jest przykład. Oto przykładowe dane wejściowe:

programming _____________ and code golf
programming puzzles ______ code ____

A oto odpowiednie wyjście:

programming ___puzzles___ and code golf
programming puzzles _and__ code golf

Na potrzeby tego wyzwania „słowo” jest zdefiniowane jako sekwencja jednej lub więcej małych liter, a „puste” jest zdefiniowane jako jeden lub więcej podkreślników (dane wejściowe zawsze będą zawierać tylko małe litery, spacje i podkreślenia) . Słowa i półfabrykaty w ciągach są oddzielone pojedynczymi odstępami, a suma liczby słów i pustych w zdaniach zawsze będą równe.

Celem wyzwania jest wypełnienie wszystkich pustych pól prawidłowymi słowami , które są słowami, które zajmują ten sam indeks w drugim ciągu po podzieleniu spacjami.

  • Słowo musi być wyśrodkowane na pustym miejscu, jak pokazano słowem „puzzle” w powyższym przykładzie - po obu stronach pozostaje taka sama liczba znaków podkreślenia.

  • Jeśli słowa nie można dokładnie wyśrodkować, dodatkowy znak podkreślenia może znajdować się po lewej lub po prawej stronie (np. Słowo „i” w powyższym przykładzie).

  • Zawsze będzie wystarczająca liczba znaków podkreślających, aby dopasować słowo, ale może być dokładnie tyle, ile długość słowa (np. Słowo „golf” w powyższym przykładzie).

  • Nigdy nie będzie spacji w tej samej pozycji w obu ciągach.

Dane wejściowe / wyjściowe mogą być dowolne z poniższych (dane wejściowe / wyjściowe niekoniecznie muszą być wykonywane tą samą metodą):

  • pojedynczy ciąg oddzielony dowolnym znakiem, który nie jest alfabetyczny, spacja lub znak podkreślenia (np. ciąg oddzielony znakiem nowej linii lub przecinek)

  • tablica / lista / itp. dwóch strun

  • dwa argumenty funkcji / wiersza poleceń (tylko dane wejściowe)

Ponieważ jest to , wygra najkrótszy kod w bajtach.

Powyższy przykład można wykorzystać jako przypadek testowy. Oto większy przypadek testowy (drugi ciąg wyjściowy może się nieznacznie różnić ze względu na różne zachowanie centrowania):

lorem _____ dolor _____ amet _______________ adipiscing elit mauris dapibus tincidunt _____________________________ accumsan fringilla proin vulputate viverra lorem fermentum dictum
lorem ipsum ______ sit _______ consectetur _______________ elit mauris dapibus tincidunt metus accumsan fringilla proin vulputate viverra lorem ____________________________ dictum

lorem ipsum dolor _sit_ amet __consectetur__ adipiscing elit mauris dapibus tincidunt ____________metus____________ accumsan fringilla proin vulputate viverra lorem fermentum dictum
lorem ipsum dolor_ sit _amet__ consectetur __adipiscing___ elit mauris dapibus tincidunt metus accumsan fringilla proin vulputate viverra lorem _________fermentum__________ dictum
Klamka
źródło
Niezłe wyzwanie na dwa dni.
Rɪᴋᴇʀ

Odpowiedzi:

5

Pyth, 30

jL;Cmm|*}J\_k.[lkhx#JdJkdCcR;Q

Pobiera dane wejściowe i wyjściowe jako listę dwóch ciągów. Stosuje dość podstawowe podejście dzielenia - zip - podwójna mapa - środek - zip - łączenie.

Wypróbuj tutaj

Rozszerzony:

jL;Cmm|*}J\_k.[lkhx#JdJkdCcR;Q   ##
                          cR;Q   ##  split
                         C       ##  zip
    mm                           ##  double map
      |*}J\_k.[lkhx#JdJkd        ##  centre
   C                             ##  zip
jL;                              ##  join

Wyjaśnię więcej, gdy będę naprawdę zadowolony, że nie mogę już grać w golfa, chociaż powinno to być dość jasne, biorąc pod uwagę wszechobecność podejścia split-zip-double map-center-zip-join i wszystko.

FryAmTheEggman
źródło
8
Ahhh, klasyczne podejście typu split-zip-double-map-center-zip-join. Z czułością pamiętam, że został użyty jako przykład wprowadzający w moim wykładzie Algorytmy 101.
Martin Ender
3
@ MartinBüttner Tak, mam złe wspomnienia, ponieważ przespałem tę klasę, musiałem rozwiązać problemy na egzaminie, stosując zamiast tego podejście duplikat-dołączenie-przeglądanie-dopasowanie-dodanie-centrum.
FryAmTheEggman
4
Pójdę nalać trochę zimnej wody do oparzenia.
Martin Ender
7

Siatkówka , 102 100 93 88 bajtów

Liczba bajtów zakłada kodowanie ISO 8859-1.

$
!¶$`
m`(?<=^(\w+ )*)(?=_.*¶(?<-1>\w+ )*(\w+))
$2
(([a-z])+)(?<-2>_)*(_*)\3|!\D+
$3$1$3

Ciągi znaków zostaną oddzielone linią. Jeśli pozostanie nieparzysta liczba podkreśleń, obce będzie po słowie.

Wypróbuj online!

Wyjaśnienie

Wydaje mi się, że jest to „podejście duplicate-append-lookback-match-add-center” lub coś bliskiego ...

$
!¶$`

Zaczynamy od zduplikowania danych wejściowych (oddzielonych znakiem !a i linią). Celem tego jest to, że możemy następnie przetwarzać oba wiersze, pobierając słowa z następnego wiersza (zamiast traktować drugi wiersz osobno).

m`(?<=^(\w+ )*)(?=_.*¶(?<-1>\w+ )*(\w+))
$2

To dodaje poprawne słowo do każdej przerwy. Zaczynamy od zliczenia bieżącej pozycji słowa za pomocą lookbehind (?<=^(\w+ )*)(pozycja jest zapisywana jako głębokość grupy 1). Następnie lookahead a) upewnia się, że jesteśmy na początku luki, dopasowując _, a następnie przechodząc do następnej linii z .*¶, dopasowuje prawidłową liczbę słów z, (?<-1>\w+ )*aby dostać się do właściwej pozycji, a następnie dopasowuje znalezione tam słowo (\w+)do grupa 2.

(([a-z])+)(?<-2>_)*(_*)\3|!\D+
$3$1$3

Ten etap wykonuje trzy czynności:

  • Usuwa podkreślenia odpowiadające każdej długości słowa. Odbywa się to poprzez policzenie długości słowa w grupie 2z, ([a-z])+a następnie dopasowanie do tylu znaków podkreślenia (które nigdy nie są odpisywane).
  • Przesuwa słowo na środek luki, chwytając połowę pozostałych znaków podkreślenia (_*)\3i odpisując $3$1$3.
  • Usuwa zduplikowane dane wejściowe, dopasowując je !\D+i zastępując niczym.
Martin Ender
źródło
4

Python 2, 109

def f(a,b):exec"print' '.join([x,y][x<'`'].center(len(x),'_')for x,y in zip(a.split(),b.split()));a,b=b,a;"*2

Funkcja przyjmuje dwa ciągi jako argumenty i wypisuje dane wyjściowe jak w przykładach. Wykorzystuje nudne podejście, str.center(width, fillchar)wykonując większość pracy.

Wypróbuj online .

grc
źródło
1
Nie sądzę, żebyś potrzebował z, chyba że coś mi umknie, możesz po prostu zrobić zamianę po wydrukowaniu i wstawieniu z.
FryAmTheEggman
@FryAmTheEggman tak, masz rację. Dzięki :)
grc
2

Ruby, 111 109 znaków

->l{l.map(&:split).transpose.map{|c|c[m=c[0]<c[1]?0:1]=c[1-m].center c[m].size,?_
c}.transpose.map{|s|s*' '}}

Dane wejściowe: tablica 2 ciągów; wyjście: tablica 2 ciągów znaków.

Przykładowy przebieg:

2.1.5 :001 > puts ->l{l.map(&:split).transpose.map{|c|c[m=c[0]<c[1]?0:1]=c[1-m].center c[m].size,?_;c}.transpose.map{|s|s*' '}}[[
2.1.5 :002 >       'programming _____________ and code golf',
2.1.5 :003 >       'programming puzzles ______ code ____',
2.1.5 :004 >       ]]
programming ___puzzles___ and code golf
programming puzzles _and__ code golf
człowiek w pracy
źródło
1

JavaScript, 194 185 bajtów

f=(m,n)=>(m=m.split` `,n=n.split` `,G=(x,i,a)=>x[0]!='_'?x:(b=(a?n:m)[i],s=x.length-b.length,(k='_'.repeat(s/2))+b+k+(s%2?'_':'')),H=(e,y)=>e.map((x,i)=>G(x,i,y)).join` `,[H(m,1),H(n)])

Pobiera dwa ciągi jako parametry i zwraca dwa ciągi jako tablicę / listę

oddalony
źródło
1

Mathematica 223

Aby to zrobić, musi istnieć krótszy sposób.

k=StringLength;m=StringSplit;
g=Partition[Riffle[m@#,m@#2],2]/.{{a_,a_}:> a<>" ",{a_,b_/; StringTake[b,1]=="_"}:> a<>" ",
{a_,b_}:>Table["_",Ceiling[z=(k@a-k@b)/2]]<>b<>""<>Table["_",Floor@z]<>" "}&;
s_~h~t_:={""<>g[s,t],""<>g[t,s]}

Przykładowy przebieg

h["programming _____________ and code golf", "programming puzzles ______ code ____"]

wprowadź opis zdjęcia tutaj

DavidC
źródło
0

Gema, 208 203 znaków

\B=@set{i;0}
<I>=@push{${v;f};$0}@incr{i}
\n=@set{v;s}@set{i;0}
 =
\E=@repeat{$i;@cmps{$f;$s;@set{f;@fill-center{$f;$s}};;@set{s;@fill-center{$s;$f}}}@set{F;$f ${F;}}@set{S;$s ${S;}}@pop{f}@pop{s}}$F\n$S

Tylko dlatego, Gema ma doskonałą funkcję dla tego zadania: .@fill-center{background;value}

Dane wejściowe: 2 oddzielone wiersze nowej linii (bez końcowej nowej linii); wynik: 2 oddzielone wiersze nowego wiersza (ze spacjami końcowymi - nie wydaje się to zabronione).

Przykładowy przebieg:

bash-4.3$ echo -ne 'programming _____________ and code golf\nprogramming puzzles ______ code ____' |
> gema '\B=@set{i;0};<I>=@push{${v;f};$0}@incr{i};\n=@set{v;s}@set{i;0}; =;\E=@repeat{$i;@cmps{$f;$s;@set{f;@fill-center{$f;$s}};;@set{s;@fill-center{$s;$f}}}@set{F;$f ${F;}}@set{S;$s ${S;}}@pop{f}@pop{s}}$F\n$S'
programming ___puzzles___ and code golf 
programming puzzles _and__ code golf 
człowiek w pracy
źródło
0

C, 197 bajtów

#define c(w,y)l=strspn(w,"_"),r=strcspn(y," "),memcpy(w+(l-r)/2,y,r),w+=l,y+=r;
main(l,v,w,y,r)char**v,*w,*y;{for(w=v[1],y=v[2];*w;w++,y++)if(*w^*y)if(*w^95)c(y,w)else c(w,y)puts(v[1]);puts(v[2]);}

Wynik

$ ./a.out "lorem _____ dolor _____ amet _______________ adipiscing elit mauris dapibus tincidunt _____________________________ accumsan fringilla proin vulputate viverra lorem fermentum dictum" "lorem ipsum ______ sit _______ consectetur _______________ elit mauris dapibus tincidunt metus accumsan fringilla proin vulputate viverra lorem ____________________________ dictum"
lorem ipsum dolor _sit_ amet __consectetur__ adipiscing elit mauris dapibus tincidunt ____________metus____________ accumsan fringilla proin vulputate viverra lorem fermentum dictum
lorem ipsum dolor_ sit _amet__ consectetur __adipiscing___ elit mauris dapibus tincidunt metus accumsan fringilla proin vulputate viverra lorem _________fermentum__________ dictum
Cole Cameron
źródło
0

ES6, 122 bajty

a=>a.map(s=>s.split` `).map((s,n,a)=>s.map((w,i)=>w<'a'?(l=w.length,t=w+a[n^1][i]+w,t.substr(t.length-l>>1,l)):w).join` `)

Bierze tablicę dwóch ciągów jako pojedynczy parametr i zwraca kolejną tablicę dwóch ciągów.

Neil
źródło