Вітаємо з отриманням 10000 репутації!


19

Після того як @ MartinBüttner досяг репутації рівно 10 000 , тепер у нас на сторінці користувачів три повні ряди в 10 тисяч користувачів ! Тепер, оскільки ми всі програмісти тут, ми любимо автоматизувати речі, а не робити їх вручну. Ваше завдання полягає в тому, щоб написати програму для автоматичного привітання нових 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 якби був користувач, репутація якого щойно стала> = 10 000.
    • Кілька розділених :Dмісцями, якщо було декілька користувачів, які зустріли або пройшли 10 000 повторень. Наприклад, :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).Мені сподобався цей коз, який був моїм представником ... привіт 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скільки нових користувачів 10k.
  • Наприкінці киньте всі дні після першого :(.

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

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 або більше в день п + 1 по порівнянні з днем п: t b\\t a.

Я також погоджуюся з Мартином Бюттнером щодо тлумачення специфікацій, і що деякі з наведених вище прикладів є помилковими, навіть до того, що приклад №2 є неправильним (повинен бути :().


Ви не повинні мати псевдонім map?
— гордий haskeller

1
Це правильно (збереження 2 байтів), але ще 10 байт можна зберегти, зробивши zінфікс та замінивши replicate (length l) xна map (const x) l. Хіба не Haskell фантастично?
— TheSpanishInquisition

це точно. Приємного гольфу! На цій ноті, бо застосування функції має найвищий пріоритет, ви повинні бути в змозі скоротити (t b)\\(t a)до t b\\t a, грати в гольф з ще 4 байта.
— гордий haskeller

Було б добре, якби якийсь код знайшов ці місця, де код можна скоротити автоматично ... Хоча проект здається трохи більшим.
— гордий haskeller

Ви маєте рацію @proudhaskeller, ці паретеси були не потрібні. Спасибі.
— TheSpanishInquisition
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.