Automatycznie nieprzewidywalnie gromadzi aliteracyjną arię

15

Dzięki @ComradeSparklePony za tytuł.

To wyzwanie powinno być bardzo proste. Otrzymasz trzy listy.

Pierwsza to lista imion w tytule.

Drugi to lista przymiotników pisanych małymi literami.

Trzecia to lista rzeczowników, pisana małymi literami.

Proszę losowo wybrać nazwę, opcjonalny przymiotnik, rzeczownik i wynik <Name>'s <adjective> <noun>. Jednak każde słowo musi zaczynać się od tej samej litery. Możesz założyć, że wszystkie słowa zaczynają się na literę. Możesz również założyć (ale zwróć uwagę, jeśli tak zrobisz):

  • że wszystkie słowa składają się wyłącznie ze znaków alfabetycznych
  • że dla każdego imienia istnieje co najmniej jeden rzeczownik
  • że dla każdego rzeczownika istnieje co najmniej jedna nazwa

Nie możesz jednak założyć, że istnieje przymiotnik dla konkretnej pary imion i rzeczowników, ponieważ przymiotnik jest opcjonalny, więc wynik nadal będzie ważny.

Nie musisz wybierać wspólnej litery w jednolity sposób, chociaż wszystkie dostępne litery muszą mieć niezerową szansę wystąpienia. Musisz jednak upewnić się, że wszystkie dane wyjściowe dla danej litery mają możliwie równą szansę wystąpienia w granicach generatora liczb losowych w Twoim języku. W przypadku przymiotnika jest to równoważne z dodatkowym wpisem oznaczającym „brak przymiotnika dla tej litery”, który ma taką samą szansę jak wszystkie inne przymiotniki dla tej litery.

Przykładowe listy danych wejściowych:

Joan Neil Nicola Oswald Sherman Stephanie
new novel old original second silent
jeep noun novel output second sheep snake

Przykładowe dane wyjściowe dla tych danych wejściowych (każda linia to osobny przykład):

Stephanie's second second
Sherman's silent snake
Oswald's original output
Nicola's novel novel
Neil's noun
Joan's jeep

Zwróć uwagę na brak dodatkowych spacji między słowami w dwóch ostatnich przykładach.

To jest , więc wygrywa najkrótszy kod, który nie łamie żadnych standardowych luk!

W mało prawdopodobnym przypadku, gdy to pomaga, możesz wpisać wszystko dużymi literami, ale nadal musisz wpisać w zdaniu.

Neil
źródło
Czy słusznie zakładamy, że program powinien zwrócić: 1 imię 1 przymiotnik (jeśli pasuje do nazwy) 1 rzeczownik? A może chcesz uzyskać dane wyjściowe dla każdej nazwy?
DavidC
1
Może powinieneś dodać „Joan” i „jeep” w swoim przykładzie, aby zilustrować fakt, że dla danego listu może nie być żadnego przymiotnika?
Arnauld
Biorąc pod uwagę przykładowe dane wejściowe, istnieje szansa na brak przymiotnika 1 na 3 (ponieważ wszystkie „listy” przymiotników są długie 2)? ... a gdyby „Joan” i „Jeep” również tam były bez jprzymiotnika, czy szansa wynosiłaby 4 na 9? Być może warto umieścić prawdopodobieństwa względem danych wyjściowych lub wyliczyć wszystkie dane wyjściowe - ponieważ rozumiem, że nie tylko „wszystkie dane wyjściowe dla danej litery ...”, ale także wszystkie różne dane wyjściowe powinny mieć jednakowe prawdopodobieństwo (podane odrębne wartości na każdej liście).
Jonathan Allan
@DavidC Przykro mi, zdaję sobie sprawę, że dodanie dodatkowych przykładów sprawiło, że stało się niejasne; tworzysz tylko jeden wiersz danych wyjściowych dla każdego wywołania.
Neil
1
@JonathanAllan Dodanie „Joan” i „jeep” nie wpłynęłoby na względne szanse na wydanie „rzeczownika Neila” w porównaniu z innymi opcjami zawierającymi „Neil” i „rzeczownik”.
Neil

Odpowiedzi:

5

Galaretka ,  27 25  24 bajtów

-1 dzięki Erikowi Outgolfer (użyj zera zamiast znaku spacji)

Ż€2¦Œpḟ€0ZḢŒuEƲƇXż“'s“”K

Pełny program przyjmujący argument w postaci sformatowanej w Pythonie listy list ciągów, która wypisuje dane wyjściowe do STDOUTt.

Wypróbuj online!

W jaki sposób?

Ż€2¦Œpḟ€0ZḢŒuEƲƇXż“'s“”K - Main Link: list of lists of lists of characters
 € ¦                     - sparse application...
  2                      - ...to indices: [2]
Ż                        - ...action: prepend a zero (place holder for no adjective)
    Œp                   - Cartesian product (all choices, including invalid ones)
       €                 - for each:
      ḟ 0                -   filter out any zeros
               Ƈ         - filter keep those for which:
              Ʋ          -   last four links as a monad:
         Z               -     transpose
          Ḣ              -     head
           Œu            -     upper-case
             E           -     all equal?
                X        - random (uniform) choice  e.g. [['B','o','b'],['b','l','u','e'],['b','a','g']]
                 ż       - zip with:
                  “'s“”  -   list [["'", 's'], []]       [[['B','o','b'],["'", 's']],[['b','l','u','e'],[]],['b','a','g']]
                       K - join with spaces              [['B','o','b'],["'", 's'],' ',['b','l','u','e'],[],' ','b','a','g']
                         - implicit (smashing) print     Bob's blue bag
Jonathan Allan
źródło
24 bajty .
Erik the Outgolfer
Ach tak, fajnie :)
Jonathan Allan
5

05AB1E ,  24 23  21 bajtów

Zakłada, że ​​dla każdej nazwy istnieje rzeczownik, na co pozwala wyzwanie.

„'s«I¯ªâI‘ʒl€нË}Ωðý

Wypróbuj online!

Wyjaśnienie

„'s«                    # append "'s" to all names in the name-list
    I¯ª                 # append an empty list to the adjective-list
       â                # cartesian product between the lists
        Iâ              # cartesian product with the noun-list
          €˜            # deep flatten each sublist
            ʒ    }      # filter, keep only lists that when
             l          # converted to lowercase
              €н        # with only heads kept
                Ë       # have all elements equal
                  Ω     # pick a valid list uniformly at random
                   ðý   # and join by spaces
Emigna
źródło
Och, ¯ªi €˜są sprytni! Miałem 26-bajtową odpowiedź, ale miałem problem z
poprawieniem
@KevinCruijssen: Tak, z tą częścią miałem również najwięcej problemów. Zajęło mi trochę czasu, aby uświadomić sobie, że ¯zamiast wypełniać pustymi łańcuchami mogę użyć zamiast tego musiałem później ręcznie wyczyścić.
Emigna
4

R , 155 148 bajtów

-7 bajtów dzięki Giuseppe (przy użyciu *dla sample)

function(x,y,z){`*`=sample
while(T)T=length(unique(c(tolower(substr(c(a<-x*1,b<-c(y,"")*1,c<-z*1),1,1)),"")))-2
paste0(a,"'s ",b,if(nchar(b))" ",c)}

Wypróbuj online!

Wykorzystuje próbkę odrzucenia: losowo narysuj nazwę, przymiotnik (być może pusty ciąg) i rzeczownik, aż do momentu dopasowania pierwszych liter. Ten warunek sprawdza się poprzez zliczenie, czy liczba unikalnych elementów w wektorze utworzonych z pierwszych liter plus pusty ciąg ma długość 2 - pozwala to na przymiotnik pusty.

Następnie wydrukuj wynik z dodatkową spacją, jeśli przymiotnik nie jest pusty.

Różne możliwości zaczynające się od tej samej litery mają jednakowe prawdopodobieństwo wystąpienia, ponieważ sampleczerpie z rozkładu równomiernego. Najłatwiej to sprawdzić, pod warunkiem, że nazwa i rzeczownik zaczynają się od tej samej litery (co jest w porządku: jeśli nie, odrzucilibyśmy). Teraz uwarunkuj wydarzenie, które akceptujemy: oznacza to, że narysujemy pusty przymiotnik lub przymiotnik rozpoczynający się tą samą literą. Każda z tych możliwości wciąż ma jednakowe prawdopodobieństwo.

105

Robin Ryder
źródło
Czy ma to taką samą szansę na pusty przymiotnik dla każdej pierwszej litery?
Nick Kennedy,
@NickKennedy Tak, ponieważ sampleczerpie z jednolitego rozkładu. Najłatwiej to sprawdzić, pod warunkiem, że nazwa i rzeczownik zaczynają się od tej samej litery (co jest w porządku: jeśli nie, odrzucilibyśmy). Teraz uwarunkuj wydarzenie, które akceptujemy: oznacza to, że rysujemy albo pusty przymiotnik, albo przymiotnik rozpoczynający się tą samą literą. Każda z tych możliwości wciąż ma jednakowe prawdopodobieństwo.
Robin Ryder,
dzięki, dobrze wyjaśnione.
Nick Kennedy,
@NickKennedy Dzięki, dodam to wyjaśnienie do postu wraz z linkiem, aby zweryfikować empirycznie, że prawdopodobieństwa są równe.
Robin Ryder
1
148 bajtów
Giuseppe
3

JavaScript (ES6),  139 124 122  120 bajtów

Zaoszczędź 2 bajty dzięki @Neil

Pobiera dane wejściowe jako (names,adjectives)(nouns).

(N,a)=>F=n=>/^(.)\S+( \1\S+)+$/i.test(s=(g=a=>a[Math.random()*a.length|0])(N)+"'s "+[(o=g([,...a]))&&o+' ']+g(n))?s:F(n)

Wypróbuj online!

Lub sprawdź rozkład przy 5 milionach losowań

W jaki sposób?

sol

g = a => a[Math.random() * a.length | 0]

sols

s = g(N) + "'s " +
    [(o = g([, ...a])) && o + ' '] +
    g(n)

Następnie sprawdzamy, czy wszystkie początkowe litery są identyczne z następującym wyrażeniem regularnym:

/^(.)\S+( \1\S+)+$/i

s

Arnauld
źródło
+[(o=g([,...a]))&&o+' ']+oszczędza 2 bajty, tak myślę?
Neil
@Neil Ah, tak. Niezłe.
Arnauld
3

Python 3 , 161 154 151 147 145 145 bajtów

( Dzięki ArBo, EmbodimentOfIgnorance, Neil, który przekazał 2, 3 i 4 bajty do mojego pierwszego golfa! )

from random import*
c=choice
def f(N,a,n):
 s=c(N);w=s[0].lower();o=N
 while o[0]!=w:o=c(n)
 print(s+"'s",c([x+" "for x in a if x[0]==w]+[""])+o)

Wypróbuj online! (z wykonaniami 500k)

  • Pobiera trzy listy jako dane wejściowe.

  • Zakłada co najmniej jeden rzeczownik dla każdego imienia.


Ten sam wynik, więcej golf-y:

Python 3 , 145 bajtów

from random import*
c=choice
def f(N,a,n):
 s=c(N);y=lambda p,e=[]:c([x+" "for x in p if x[0]==s[0].lower()]+e);print(s+"'s",y(a,[""])+y(n)[:-1])

Wypróbuj online! (z wykonaniami 500k)

To tylko 140, jeśli końcowe białe spacje są dozwolone (przez usunięcie kwadratowej twarzy [:-1])

Nicola Sap
źródło
1
Ładna pierwsza odpowiedź! Można zapisać bajt w pierwszej pętli while: while t>""<t[0]!=w. Możesz także zastąpić ostatni wiersz print(s+"'s",t+(t and" ")+o), upuszczając u=trzeci wiersz.
ArBo
Ostatecznie zmieniłem swoje rozwiązanie, ponieważ poprzednie nie spełniało wymagań
Nicola Sap
1
152 bajty (stopka usunięta, by pasowała do adresu URL w komentarzu)
Embodiment of Ignorance
1
Używasz zmiennej ttylko raz, więc możesz zapisać 4 bajty, wstawiając kod. Myślę, że możesz przełączyć się ona użycie podobnego wzorca kodu t, a następnie zapisać kolejne 4 bajty, wpisując to również.
Neil
Dzięki, naprawdę pomagacie! @Neil, nie jestem w stanie refaktoryzować o: osiągam to: from random import* c=choice def f(N,a,n): s=c(N);y=lambda p,e=[]:c([x for x in p if x[0]==s[0].lower()]+e);print(s+"'s",y(a,[""])+y(n))( 137 ), ale dodanie warunkowego spacji za pomocą opcjonalnego argumentu do ykosztuje mnie 11 bajtów
Nicola Sap
0

Galaretka , 28 bajtów

1ịZḢXɓŒuḢ=ɗƇ€Ż€2¦X€ḟ0ż“'s“”K

Wypróbuj online!

Napisałem to, zanim zobaczyłem krótszą odpowiedź @ JonathanAllan, ale pomyślałem, że warto opublikować, ponieważ stosuje inne podejście. Zapisano 3 bajty według sugestii @ EriktheOutgolfer dotyczącej tej odpowiedzi.

Pełny program pobierający listę list ciągów i domyślnie drukujący losowo wybrane aliteracje. Zakłada co najmniej jeden rzeczownik na imię.

Nick Kennedy
źródło
0

C # (interaktywny kompilator Visual C #) , 176 bajtów

(a,b,c)=>(a=a[z.Next(a.Count)])+"'s "+b.Where(x=>(x[0]&95)==a[0]).Append("").OrderBy(x=>z.Next()).Last()+" "+c.OrderBy(x=>z.Next()).Last(x=>(x[0]&95)==a[0]);var z=new Random();

Wypróbuj online!

Wcielenie ignorancji
źródło
Możesz założyć, że nazwy zaczynają się od dużej litery, więc możesz po prostu wpisać duże litery w celu porównania, co powinno zaoszczędzić 10 bajtów?
Neil
@ Nee Yep, dokładnie 10 bajtów :)
of Ignorance
0

Czerwony , 179 bajtów

func[a b c][random a random c
foreach k c[if k/1 = h: a/1/1 + 32[g: rejoin[sp k]]]collect/into[foreach
d b[if d/1 = h[keep rejoin[sp d]]]]e: copy[""]random e rejoin[a/1"'s"e/1 g]]

Wypróbuj online!

Wyjaśnienie:

Red[]
f: func[a b c][                     ; a function with 3 arguments
    random a                        ; shuffle the list of names in place
    random c                        ; shuffle the list of nouns in place
    foreach k c [                   ; for each item in the shuffled list of nouns
        if k/1 = h: a/1/1 + 32 [    ; check if it begins with the same lowercase letter
                                    ; as the first name in the shuffled list of names
            g: rejoin [" " k]       ; if yes, then insert a " " in front of it save it as g
        ]                           ; thus I always get the last match
    ]
    collect/into [                  ; collect in a new list e
        foreach d b [               ; all items form the adjectives list
            if d/1 = h [            ; that start with the same lowercase letter as the 1st noun
                keep rejoin [" " d] ; insert a " " in form of the adjective
            ]
        ]
    ] e: copy[""]                   ; the list initially has a single item - the empty string
   random e                         ; shuffle the extracted adjectives list
   rejoin [a/1 "'s" e/1 g]          ; return the formatted string
]
Galen Iwanow
źródło
0

Scala , 234 226 234 206 bajtów

-28 z powodu faktu, że myślałem, że musi zaakceptować StdIn, jest to teraz funkcja

def f(a:List[String],b:List[String],c:List[String])=scala.util.Random.shuffle(for(d<-a;e<-("" +: b);g<-c;if(d.head.toLower==g.head&&(e.isEmpty||e.head==g.head))) yield s"$d's $e $g".replace("  ", " ")).head

Wypróbuj online!

Nie golfowany:

def f(names: List[String], adjectives: List[String], nouns: List[String]) = {
  val allPossible = for {
    name <- names
    adjective <- ("" +: adjectives) // Add the choice of no adjective
    noun <- nouns
    if (name.head.toLower == noun.head && (adjective.isEmpty || adjective.head == noun.head)) // Filter out so only matching entries remain
  } yield
    s"$name's $adjective $noun"
      .replace("  ", " ") // Get rid of artifact created by the empty adjective selection

  scala.util.Random.shuffle(allPossible.toList).head // Get a random element
}
Soren
źródło
0

Ruby , 94 bajty

->a,b,c{"#{n=a.sample}'s #{s=[p,*b.grep(r=/^#{n[0]}/i)].sample;s+" "if s}#{c.grep(r).sample}"}

Wypróbuj online!

Wartość tuszu
źródło
0

Ikona , 167 163 bajtów

procedure f(a,b,c)
!a:=:?a&\x;!c:=:?c&\x;d:=[""]
e:=!b&e[1]==(t:=char(32+ord(a[1,1])))&put(d," "||e)&\x
!d:=:?d&\x;return(!a||"'s"||!d||" "||(k:=!c&t==k[1]&k))
end

Wypróbuj online!

Używa tego samego algorytmu co moja Redodpowiedź.

Galen Iwanow
źródło