Gratulujemy zdobycia 10 000 reputacji!

19

Po tym, jak @ MartinBüttner osiągnął dokładnie 10 000 reputacji , na stronie użytkowników mamy teraz trzy pełne rzędy 10 000 użytkowników ! Ponieważ wszyscy jesteśmy tutaj programistami, lubimy automatyzować rzeczy zamiast robić je ręcznie. Twoim wyzwaniem jest napisanie programu, który automatycznie pogratuluje nowym 10 000 użytkownikom.

Specyfikacja

Wejście

Wprowadzane będą nwiersze liczb oddzielonych spacją. (Jeśli chcesz, możesz również wziąć pojedynczą listę liczb oddzielonych przecinkami, jeśli to skraca kod.) Na przykład:

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

Lub:

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

Każda lista liczb reprezentuje listę wartości reputacji użytkowników w jednym dniu.

Wynik

Dane wyjściowe będą mieć taką samą liczbę nwierszy (lub listę rozdzielaną przecinkami o tej samej długości). Każda pozycja / pozycja będzie:

  • :D jeśli był użytkownik, którego reputacja właśnie osiągnęła> = 10 000.
    • Wiele oddzielonych spacjami, :Djeśli wielu użytkowników spełniło lub przekroczyło liczbę 10 000 powtórzeń. Na przykład :D :D :Ddla 3 nowych 10 000 użytkowników.
  • :( a następnie zatrzymać dalsze dane wyjściowe, jeśli dane wejściowe są niejednoznaczne lub niemożliwe (więcej na ten temat w następnej sekcji).
  • nic, jeśli żaden z tych warunków nie jest spełniony.

Dwuznaczność

Możliwe, że dane wejściowe są niejednoznaczne. Na potrzeby tego wyzwania zakładamy, że:

  • Limit reputacji wynosi 200 dziennie, ignorując akceptacje i nagrody itp. Ze względu na wyzwanie.
  • Użytkownicy nie mogą stracić reputacji (ponownie ze względu na prostotę i wyzwanie).

Dane wejściowe uważa się za niejednoznaczne, gdy nie można ustalić, które wartości reputacji odpowiadają danemu użytkownikowi. Na przykład na wejściu 10 20,30 40nie można stwierdzić, czy użytkownik 10 powtórzeń stał się użytkownikiem 30 powtórzeń, czy użytkownikiem 40 powtórzeń.

Wkład uważa się za niemożliwy, gdy użytkownicy z jednego dnia nie mogliby zostać użytkownikami z następnego dnia. Na przykład w danych wejściowych 10 20,310 320ta sytuacja jest wyraźnie niemożliwa, ponieważ użytkownicy nie mogliby zyskać 300 reputacji dziennie. Utrata reputacji przez użytkowników jest również niemożliwa.

Obudowy brzegowe

  • Początkowe wartości reputacji mogą zaczynać się od czegokolwiek (tj. Użytkownik może zacząć od reputacji 1337).
  • Brak danych wyjściowych dla pierwszego wiersza / elementu listy.
  • Dane wejściowe zawsze będą poprawne pod względem składniowym, co oznacza, że ​​wartości reputacji będą zawsze dodatnimi liczbami całkowitymi, zawsze będzie taka sama ilość wartości reputacji na wiersz / pozycję listy itp.
  • Wartości reputacji nie są sortowane; mogą być w dowolnej kolejności.

Przypadki testowe

Wejście: 9900,10000
Wyjście::D

Wejście: 9900 9950 9910,10100 9950 9910,10300 10150 10110
Wyjście::D,:D :D

Wejście: 10 20 30,42 10 20,10 242 20,442 42 10,0 0 0,442 42 10
Wyjście:,,,:(

Wejście: 10 20,15 25,15 25
Wyjście:,,

Wejście: 9999 9998 9997,10000 9998 9997,10000 10000 9997,10300 10000 10000
Wyjście::D,:D,:(

Wejście: 100,90,80,70
Wyjście::(

Wejście: 10000 10000 10000 9999,10000 10000 10000 10000,10010 10020 10030 10040
Wyjście::D,:(

Wejście: 9999 9998 9997 9996,10196 10197 10198 10199,10399 10199 10197 10196
Wyjście::D :D :D :D,

Klamka
źródło
@ MartinBüttner Ah, nie zauważyłem tego. Naprawiono
Klamka
Pierwszy krok w tym przykładzie jest również niejednoznaczny.
Martin Ender,
1
Natomiast przykład 4 nie jest dwuznaczny.
Martin Ender
(i.e. a user can start with 1337 reputation).Podobało mi się to, ponieważ było to moje rep ... wel 5 min temu, aż ktoś głosował jedną z moich odpowiedzi xD
Teun Pronk
Przykład 5, krok 2 jest również niejednoznaczny (który z 10 000 użytkowników jest?). To samo dotyczy na przykład 7 (chyba że dodasz jakąś zasadę, że rozróżnianie użytkowników o równej liczbie powtórzeń jest nieistotne, ale skąd wiesz, który użytkownik był który z pierwszego dnia, jeśli związał się z kimś innym później?)
Martin Ender

Odpowiedzi:

12

Rubinowy, 209 bajtów

Edycja: Zmieniłem na Ruby, co skróciło to o około 30%. Zobacz historię edycji oryginalnej wersji Mathematica. Podejrzewam, że główne oszczędności wynikają z tego, że Ruby permutationnie ignoruje przełączanych pozycji identycznych elementów (w co musiałem oszukać Mathematica).

Używa formatu rozdzielonego znakiem nowej linii.

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

Istota tego jest taka:

  • Zbierz wszystkie kolejne pary dni.
  • Uzyskaj wszystkie permutacje poprzedniego dnia i odejmij każdą z nich od bieżącego dnia.
  • Porzuć wszystkie wyniki, które zawierają różnice, które są ujemne lub większe 200.
  • Jeśli liczba pozostałych permutacji nie wynosi 1, wyjdź :(.
  • W przeciwnym razie wypisz tyle, :Dile jest nowych 10 000 użytkowników.
  • Na koniec upuść wszystkie dni po pierwszym :(.

Mniej golfa:

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

Myślę, że to jeden piękny łańcuch liczników. :)

PS: Czy to dziwne, że jako pierwszy odpowiedziałem na to pytanie?

Martin Ender
źródło
8
Nie sądzę, że to dziwne. Coś mi mówi, że masz przewagę na boisku;)
Hobby Calvina
Więc to zawiedzie niektóre przykłady w pytaniu, prawda?
Cruncher
@Cruncher Nie powiedzie się te, które moim zdaniem są nieprawidłowe zgodnie ze specyfikacją (jak wspomniałem w komentarzach). Jeśli Doorknob zdecyduje się zmienić specyfikację zamiast naprawiać przykłady, myślę, że będę musiał to przerobić.
Martin Ender,
@ MartinBüttner Tak właśnie wymyśliłem. Właśnie potwierdzam :)
Cruncher
6

Haskell, 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

Małe wyjaśnienie: Algorytm jest bardzo podobny do tego, który zastosował MartinBüttner, z wyjątkiem tego nub, nad którym zastanawiałem się. Należy zauważyć, że do ustalenia, o ile więcej wartości reputacji wynosi 10000 lub więcej w dniu n + 1, w porównaniu do dnia n: używana jest różnica listy t b\\t a.

Zgadzam się również z MartinBüttner w sprawie interpretacji specyfikacji i że niektóre z powyższych przykładów są błędne, nawet do tego stopnia, że ​​przykład nr 2 jest zły (powinien być :().

TheSpanishInquisition
źródło
Nie powinieneś pseudonim map?
dumny haskeller
1
To prawda (oszczędność 2 bajty), ale kolejne 10 bajtów mogą być zapisywane poprzez zInfix i zastępowanie replicate (length l) xz map (const x) l. Czy Haskell nie jest fantastyczny?
TheSpanishInquisition
to na pewno jest. Miłej gry w golfa! W tym pamiętać, Ponieważ aplikacja funkcja ma najwyższy priorytet, powinno być możliwe, aby skrócić (t b)\\(t a)do t b\\t a, gra w golfa na 4 kolejne bajty.
dumny haskeller
Byłoby miło, gdyby istniał jakiś kod, aby znaleźć miejsca, w których kod może być automatycznie skracany ... Wydaje się to jednak trochę dużym projektem.
dumny haskeller
Masz rację @proudhaskeller, te paretheses były niepotrzebne. Dzięki.
TheSpanishInquisition