Автоматически предсказуемо собрать аллитеративную арию


15

Спасибо @ComradeSparklePony за название.

Эта задача должна быть очень простой. Вам даны три списка.

Первый - это список имен в заглавном случае.

Второй список прилагательных в нижнем регистре.

Третий список существительных, в нижнем регистре.

Пожалуйста, выберите случайным образом имя, необязательное прилагательное, существительное и вывод <Name>'s <adjective> <noun>. Однако каждое слово должно начинаться с одной и той же буквы. Вы можете предположить, что все слова начинаются с буквы. Вы также можете предположить (но отметьте в своем ответе, если вы делаете):

  • что все слова состоят исключительно из буквенных символов
  • что для каждого имени есть хотя бы одно существительное
  • что для каждого существительного есть хотя бы одно имя

Однако вы не можете предполагать, что прилагательное существует для определенной пары имени и существительного, так как прилагательное является необязательным, поэтому вывод все еще будет действительным.

Вам не нужно выбирать общую букву единообразно, хотя все доступные буквы должны иметь ненулевую вероятность появления. Однако вы должны убедиться, что все выходные данные для данной буквы имеют как можно более равные шансы на появление в пределах генератора случайных чисел на вашем языке. В случае с прилагательным это эквивалентно наличию дополнительной записи, означающей «нет прилагательного для этой буквы», которая имеет такой же шанс, как и все другие прилагательные для этой буквы.

Примеры списков ввода:

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

Пример выходов для этих входов (каждая строка является отдельным примером):

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

Обратите внимание, что в последних двух примерах между словами нет пробела.

Это , поэтому выигрывает самый короткий код, который не нарушает стандартные лазейки!

В маловероятном случае, если это поможет, вы можете вводить все в верхнем регистре, но вам все равно нужно выводить в предложении.


Правильно ли считать, что программа должна возвращать: 1 имя 1 прилагательное (если имя соответствует имени) 1 существительное? Или вы просите произвести вывод для каждого имени?
DavidC

1
Может быть, вы должны добавить «Джоан» и «джип» в вашем примере, чтобы проиллюстрировать тот факт, что для данного письма вообще не может быть прилагательного?
Арно

Учитывая ваш пример ввода, есть ли вероятность, что прилагательное 1 в 3 (так как все прилагательные "списки" 2 длинные)? ... и если бы «Джоан» и «Джип» тоже были без jприлагательных, шанс стал бы 4 из 9? Может быть, стоит поместить вероятности в зависимости от выходных данных или перечислить все выходные данные - насколько я понимаю, не только «все выходные данные для данной буквы ...», но также и все различные выходные данные должны иметь равную вероятность (учитывая различные значения в каждом списке).
Джонатан Аллан

@DavidC Извините, я понимаю, добавление дополнительных примеров сделало это неясным; вы производите только одну строку вывода для каждого вызова.
Нейл

1
@JonathanAllan Добавление «Джоан» и «Джип» не повлияет на относительные шансы вывода «существительного Нейла» по сравнению с другими параметрами, содержащими «Нил» и «существительное».
Нейл

Ответы:


5

Желе ,  27 25  24 байта

-1 благодаря Эрику Искателю (используйте символ пробела вместо пробела)

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

Полная программа, принимающая аргумент в виде отформатированного в Python списка списков строк, который печатает вывод в STDOUTt.

Попробуйте онлайн!

Как?

Ż€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


Ах да, здорово :)
Джонатан Аллан

5

05AB1E ,  24 23  21 байт

Предполагается, что для каждого имени существует существительное, разрешенное вызовом.

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

Попробуйте онлайн!

объяснение

„'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

Ох, ¯ªи €˜умны! У меня был 26-байтовый ответ, но у меня были проблемы с исправлением двойного пробела, когда нет прилагательного.
Кевин Круйссен

@KevinCruijssen: Да, это была часть, с которой у меня тоже было больше всего проблем. ¯Мне потребовалось некоторое время, чтобы понять, что я мог бы использовать вместо заполнения пустыми строками, которые мне пришлось потом убирать вручную.
Эминья

4

R , 155 148 байт

-7 байт благодаря Джузеппе (используется *для 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)}

Попробуйте онлайн!

Используется выборка отклонения: нарисуйте случайным образом имя, прилагательное (возможно, пустую строку) и существительное, пока не совпадут первые буквы. Это условие проверяется путем подсчета, если количество уникальных элементов в векторе, образованном из первых букв плюс пустая строка, имеет длину 2 - это допускает пустое прилагательное.

Затем выведите результат с дополнительным пробелом, если прилагательное не пустое.

Различные возможности, начинающиеся с одной и той же буквы, имеют равные вероятности появления, поскольку sampleоснованы на равномерном распределении. Самый простой способ убедиться в этом состоит в том, чтобы при условии, что имя и существительное начинаются с одной и той же буквы (это нормально: если они этого не делают, мы бы отклонили). Теперь условие для события, которое мы принимаем: это означает, что мы рисуем либо пустое прилагательное, либо прилагательное, начинающееся с той же буквы. Каждая из этих возможностей все еще имеет равную вероятность.

105


Имеет ли это равный шанс для пустого прилагательного по отношению друг к другу для любой данной первой буквы?
Ник Кеннеди

@NickKennedy Да, так как sampleрисует из равномерного распределения. Самый простой способ убедиться в этом состоит в том, чтобы при условии, что имя и существительное начинаются с одной и той же буквы (это нормально: если они этого не делают, мы бы отклонили). Теперь условие для события, которое мы принимаем: это означает, что мы рисуем либо пустое прилагательное, либо прилагательное, начинающееся с той же буквы. Каждая из этих возможностей все еще имеет равную вероятность.
Робин Райдер

спасибо, хорошо объяснил.
Ник Кеннеди

@NickKennedy Спасибо, я добавлю это объяснение к сообщению вместе со ссылкой, чтобы эмпирически проверить, что вероятности равны.
Робин Райдер


3

JavaScript (ES6),  139 124 122  120 байт

Сохранить 2 байта благодаря @Neil

Принимает вход как (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)

Попробуйте онлайн!

Или проверьте распределение на 5 миллионов розыгрышей

Как?

грамм

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

граммs

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

Затем мы проверяем, все ли начальные буквы идентичны с помощью следующего регулярного выражения:

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

s


+[(o=g([,...a]))&&o+' ']+ экономит 2 байта, я думаю?
Нейл

@ Нил Ах, да. Хороший.
Арно

3

Python 3 , 161 154 151 147 145 байтов

( Спасибо ArBo, EmbodimentOfIgnorance, Нил, который вложил 2, 3 и 4 байта в мой первый гольф! )

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)

Попробуйте онлайн! (с 500к казней)

  • Принимает три списка в качестве входных данных.

  • Принимает хотя бы одно существительное для каждого имени.


Тот же счет, больше гольф-у:

Python 3 , 145 байт

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])

Попробуйте онлайн! (с 500к казней)

Это просто 140, если разрешены конечные пробелы (удалив квадратное лицо [:-1] )


1
Хороший первый ответ! Вы можете сохранить байты в первом цикле в то время как: while t>""<t[0]!=w. Вы также можете заменить последнюю строку print(s+"'s",t+(t and" ")+o), опустив u=в третьей строке.
АрБо

Я закончил тем, что изменил свое решение, потому что предыдущий не соответствовал требованиям
Никола Сап

1
152 байта (нижний колонтитул удален, чтобы соответствовать URL в комментарии)
Воплощение невежества

1
Вы используете переменную tтолько один раз, поэтому вы можете сохранить 4 байта, вставив код. Я думаю, что вы можете переключиться oна использование аналогичного шаблона кода t, а затем сохранить еще 4 байта, вставив это тоже.
Нейл

Спасибо, ребята, вы действительно помогаете! @Neil, я не смог провести рефакторинг o: я достиг этого: 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 ), но добавление условного пробела через необязательный аргумент arg yстоит мне 11 байтов
Никола Сап

0

Желе , 28 байт

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

Попробуйте онлайн!

Написал это до того, как увидел короткий ответ @ JonathanAllan, но подумал, что это стоит опубликовать, поскольку в нем используется другой подход. Сохранено 3 байта предложением @ EriktheOutgolfer для этого ответа.

Полная программа, содержащая список списков строк и неявно печатающая случайно выбранную аллитерацию. Принимает хотя бы одно существительное на имя.


0

C # (интерактивный компилятор Visual C #) , 176 байт

(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();

Попробуйте онлайн!


Вы можете предположить, что имена начинаются с заглавной буквы, поэтому вы можете просто использовать другие заглавные буквы для сравнения, что должно сэкономить вам 10 байт?
Нил

@Neil Да, ровно 10 байтов :)
Воплощение Невежества

0

Красный , 179 байт

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]]

Попробуйте онлайн!

Объяснение:

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
]

0

Scala , 234 226 234 206 байт

-28 из-за того, что я думал, что должен был принять StdIn, теперь это функция

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

Попробуйте онлайн!

Ungolfed:

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
}


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.