Поздравляем с получением 10000 репутации!

19

После того, как @ MartinBüttner достиг ровно 10000 репутаций , мы теперь имеем три полных ряд 10k пользователей на странице пользователей ! Теперь, поскольку мы все здесь программисты, нам нравится автоматизировать вещи, а не делать это вручную. Ваша задача - написать программу для автоматического поздравления новых пользователей 10k.

Спецификация

вход

На входе будут nстроки разделенных пробелами чисел. (Если вы хотите, вы также можете взять один список разделенных запятыми чисел, если это делает ваш код короче.) Например:

10 20 30 40 50
15 25 35 45 55
20 30 40 50 60

Или:

10 20 30 40 50,15 25 35 45 55,20 30 40 50 60

Каждый список чисел представляет собой список значений репутации пользователей за один день.

Выход

На выходе будет одинаковое количество nстрок (или список через запятую одинаковой длины). Каждая строка / элемент списка будет:

  • :D если бы был пользователь, чья репутация только что стала> = 10000.
    • Несколько разделенных пробелами :Ds, если было несколько пользователей, которые встретили или прошли счет 10000 представителей. Например, :D :D :Dдля 3 новых 10k пользователей.
  • :( и затем остановите дальнейший вывод, если ввод неоднозначен или невозможен (подробнее об этом в следующем разделе).
  • ничего, если ни одно из этих условий не выполняется.

неоднозначность

Возможно, что ввод неоднозначен. Для целей этой задачи мы предполагаем, что:

  • Предел репутации составляет 200 в день, игнорируя принятие и щедрости и тому подобное ради вызова.
  • Пользователи не могут потерять репутацию (опять же за простоту и за вызов).

Ввод считается неоднозначным, когда невозможно определить, какие значения репутации соответствуют какому-либо пользователю. Например, во входных данных 10 20,30 40вы не можете сказать, стал ли пользователь с 10 повторениями пользователем с 30 повторениями или пользователем с 40 повторениями.

Ввод считается невозможным, если пользователи одного дня не могли стать пользователями следующего дня. Например, во входных данных 10 20,310 320эта ситуация явно невозможна, потому что пользователи не могли получить 300 репутации за день. Пользователям потерять репутацию тоже невозможно.

Краевые случаи

  • Начальные значения репутации могут начинаться с чего угодно (то есть пользователь может начать с репутации 1337).
  • Нет выхода для первой строки / элемента списка.
  • Входные данные всегда будут синтаксически действительными, что означает, что значения репутации всегда будут положительными целыми числами, всегда будет одинаковое количество значений репутации на строку / элемент списка и т. Д.
  • Значения репутации не сортируются; они могут быть в любом порядке.

Контрольные примеры

Вход: 9900,10000
Выход::D

Вход: 9900 9950 9910,10100 9950 9910,10300 10150 10110
Выход::D,:D :D

Вход: 10 20 30,42 10 20,10 242 20,442 42 10,0 0 0,442 42 10
Выход:,,,:(

Вход: 10 20,15 25,15 25
Выход:,,

Вход: 9999 9998 9997,10000 9998 9997,10000 10000 9997,10300 10000 10000
Выход::D,:D,:(

Вход: 100,90,80,70
Выход::(

Вход: 10000 10000 10000 9999,10000 10000 10000 10000,10010 10020 10030 10040
Выход::D,:(

Вход: 9999 9998 9997 9996,10196 10197 10198 10199,10399 10199 10197 10196
Выход::D :D :D :D,

Дверная ручка
источник
@ MartinBüttner Ах, не заметил этого. Исправлено
дверная ручка
Первый шаг в этом примере также неоднозначен.
Мартин Эндер
1
Принимая во внимание, что пример 4 не является двусмысленным.
Мартин Эндер
(i.e. a user can start with 1337 reputation).Мне понравился этот coz, который был моим представителем 5 минут назад, пока кто-то не проголосовал за один из моих ответов xD
Teun Pronk
Пример 5, шаг 2 также неоднозначен (какой пользователь 10k какой?). То же самое относится, например , 7 (если не добавить некоторые правила, различая пользователей равных респ не имеет отношения, но потом , как вы знаете , какой пользователь был который на один день, если он связан с кем - то еще позже?)
Мартин Эндер

Ответы:

12

Рубин, 209 байт

Изменить: я перешел на Ruby, который сократил это примерно на 30%. Смотрите историю изменений для оригинальной версии Mathematica. Я полагаю, что основная экономия заключается в том, что Руби permutationне игнорирует переключение позиций одинаковых элементов (что мне пришлось обмануть Mathematica).

Это использует формат новой строки.

gets.split('
').map{|s|s.split.map &:to_i}.each_cons(2){|a,b|a.permutation.map{|q|q.zip(b).map{|x,y|y-x}}.reject{|d|d.any?{|x|x<0||x>200}}.size!=1?abort(':('):(puts':D '*(a.count{|d|d<1e4}-b.count{|d|d<1e4}))}

Суть заключается в следующем:

  • Получите все последовательные пары дней.
  • Получите все перестановки предыдущего дня и вычтите каждую из них из текущего дня.
  • Отбросьте все результаты, которые содержат различия, которые являются отрицательными или большими 200.
  • Если число оставшихся перестановок не равно 1, выведите :(.
  • В противном случае выведите столько пользователей, :Dсколько появятся новых 10 000 пользователей.
  • В конце бросьте все дни после первого :(.

Меньше гольфа:

gets.split("\n").map{|s|
  s.split.map &:to_i
}.each_cons(2){|a,b|
  a.permutation.map{|q|
    q.zip(b).map{|x,y|
      y-x
    }
  }.reject{|d|
    d.any?{|x|
      x<0||x>200
    }
  }.size!=1 ? abort(':(') : (puts ':D '*(a.count{|d|d<1e4}-b.count{|d|d<1e4}))
}

Я думаю, что это одна прекрасная цепочка счетчиков. :)

PS: странно ли, что я первый отправил ответ на этот вопрос?

Мартин Эндер
источник
8
Я не думаю, что это странно. Что-то подсказывает мне, что у вас есть преимущество на домашнем поле;)
Увлечения Кэлвина
Так что это потерпит неудачу в некоторых из примеров в вопросе, верно?
Cruncher
@Cruncher Это потерпит неудачу те, которые я считаю неправильными в соответствии со спецификацией (как я уже упоминал в комментариях). Если Doorknob решит изменить спецификацию вместо исправления примеров, я думаю, мне придется переделать это.
Мартин Эндер
@ MartinBüttner Вот что я понял. Просто подтверждаю :)
Cruncher
6

Хаскелл, 254 249 244 232 228

import Data.List
t=m(9999<)
p(a:b:r)=(a,b,r)%(filter(all(`elem`[0..200]))$nub$m(zipWith(-)b)$permutations a)
p _=""
(a,b,r)%(_:[])=(concat$m(const":D ")$t b\\t a)++'\n':p(b:r)
_%_=":("
m=map
main=interact$p.m(m read.words).lines

Небольшое объяснение: алгоритм очень похож на алгоритм, используемый MartinBüttner, за исключением того, nubчто я немного подумал. Обратите внимание, что разница в списке используется для определения того, сколько значений репутации на 10000 или больше в день n + 1 по сравнению с днем ​​n : t b\\t a.

Я также согласен с MartinBüttner в интерпретации спецификаций и в том, что некоторые из приведенных выше примеров неверны, даже до такой степени, что пример № 2 неверен (должен быть :().

TheSpanishInquisition
источник
Вы не должны псевдоним map?
гордый haskeller
1
Это верно (сохранение 2 байта), но еще 10 байтов можно сохранить, создав zинфикс и заменив его replicate (length l) xна map (const x) l. Разве Хаскелл не фантастичен?
TheSpanishInquisition
это точно. Приятно играть в гольф! В связи с этим, поскольку приложение функции имеет наивысший приоритет, вы должны быть в состоянии сократить (t b)\\(t a)до t b\\t a, играя в гольф еще 4 байта.
гордый haskeller
Было бы неплохо, если бы был какой-то код, чтобы найти эти места, где код может быть автоматически сокращен ... Хотя проект кажется немного большим.
гордый haskeller
Вы правы @proudhaskeller, эти паретезы были не нужны. Благодарю.
TheSpanishInquisition