Płyniesz kajakiem po dość szybkiej rzece o białych wodach. Nagle wiosła eksplodują i znajdujesz się w niebezpiecznej sytuacji, pędzącej szybko rzeką bez żadnych wioseł. Na szczęście nadal masz umiejętności programistyczne, więc postanawiasz wykuć program na boku kajaka, aby pomóc ci przetrwać bystrza. Jednak z boku czółna nie ma zbyt dużej powierzchni do pisania programu, więc program musi być jak najkrótszy.
Rzekę można przedstawić jako siatkę 8 na 16. Oznaczymy kolumny liczbami 0
do 7
i wierszy liczbami 0
do 15
.
y
--------15
--------14
--------13
--------12
--------11
--------10
--------9
--------8
--------7
--------6
--------5
--------4
--------3
--------2
--------1
--------0
01234567
x
Powyżej: całkowicie spokojna, zwykła rzeka bez przeszkód. Oczywiście nie jest to rzeka, na której płyniesz.
Zaczynasz od współrzędnej (4, 0), a stamtąd poruszasz się w sposób niekontrolowany w górę rzeki (tj. Wektora (0,1)
), aż uderzysz w skałę (reprezentowaną przez o
w tych przykładach jako). Kiedy uderzysz w skałę, będziesz miał 55% szansy na przejście obok skały w lewo (tj. Wektor (-1,1)
) i 45% szansy na przejście obok skały w prawo (tj. Wektor (1,1)
). Jeśli czółno znajduje się na skrajnych lewych lub prawych kolumnach, zawsze przesunie się w kierunku środka. Jeśli nie ma skał, przesunie się prosto w górę.
y
----x---15
----xo--14
-o--x---13
----x---12
---ox---11
---x----10
---xo---9
---ox---8
----xo--7
-----x--6
----ox--5
-o--x---4
----x---3
----xo--2
----x---1
----x---0
01234567
Powyżej: możliwa trasa, którą może płynąć kajak, przedstawiony za pomocą postaci x
Biorąc pod uwagę mapę rzeki, napisz program, który wyświetli prawdopodobieństwo zakończenia czółna w danej kolumnie.
Zaakceptuj dane wejściowe dowolną metodą dogodną dla Twojego programu (np. STDIN, argument wiersza poleceń raw_input()
, odczyt z pliku itp.). Pierwsza część danych wejściowych to pojedyncza liczba całkowita od 0 do 7, reprezentująca kolumnę, dla której program znajdzie prawdopodobieństwo. Poniżej znajduje się lista krotek w formie x,y
reprezentującej pozycję kamieni.
Przykład:
Wkład:
4 4,1 5,5 3,5
Oznaczałoby to rzekę ze skałami w pozycjach (4,1), (5,5) i (3,5) i prosi o prawdopodobieństwo, że kajak zakończy się w czwartej kolumnie.
Wydajność:
0.495
Należy zauważyć, że w tym przykładzie położenia skał były symetryczne, co pozwoliło rozwiązać problem z rozkładem dwumianowym. Nie zawsze tak będzie!
Ponadto rzekę zawsze można pokonywać. Oznacza to, że nigdy nie będzie dwóch skał, które byłyby ustawione poziomo obok siebie. Zobacz komentarz Glenna, aby zobaczyć przykład niemożliwego przypadku.
To jest kod golfowy, więc wygrywa najmniejsza liczba znaków. Jeśli specyfikacja nie jest jasna, możesz zadawać pytania w komentarzach.
Odpowiedzi:
GolfScript, 105 znaków
Wersja GolfScript, która stała się znacznie dłuższa niż zamierzona - ale każda próba z innym podejściem była jeszcze dłuższa. Dane wejściowe należy podać na STDIN.
Przykład:
Kod z adnotacjami:
źródło
Ruby,
204191172 znakówRekurencyjnie symuluje wszystkie możliwe wyniki, jednocześnie śledząc prawdopodobieństwo każdego wyniku, a następnie dodaje to prawdopodobieństwo do licznika skumulowanego, kiedy
y == 15
.Fantazyjne sztuczki:
c,*r=gets.split
- operator „splat” (*
) pobiera wszystkie pozostałe elementygets.split
i umieszcza je wr
tablicynext {something} if {condition}
: zasadniczo równoważne z„Odkryte” poprzez ewolucję odif condition; something; return; end
doreturn something if condition
dobreak something if condition
, a potem pomyślałem, że spróbuję krótszego „operatora pętli”, aby zobaczyć, czy zadziała (co oczywiście zrobiło).Dzięki @ MartinBüttner za sugestię użycia przyklejonych operatorów trójskładnikowych (co ostatecznie stało się ogromną trzecią linią w powyższym kodzie golfowym) i wyeliminowanie powyższego punktu (co uratowało 19 (!) Znaków).
Użyłem jednak nieco fantazyjnej sztuczki: zdałem sobie sprawę, że
s[foo],s[bar]
nie działa w Ruby dla dwóch wywołań metod w jednej instrukcji. Więc w pierwszej chwili zmienił go do(_=s[foo],s[bar])
(zmiennej obojętne), ale potem zdałem sobie sprawę, mogę tylko dodać i wyrzucić wartości zwracanych:s[foo]+s[bar]
. Działa to tylko dlatego, że wywołania do zawszes
będą „zwracać” inne połączenias
lub numer (o[x]+=p
), więc nie muszę się martwić o sprawdzenienil
.Inne różne optymalizacje:
p
zamiastputs
do drukowania liczb,<1
zamiast==0
(ponieważ kajak nigdy nie opuszcza rzeki) i podobnych porównań gdzie indziej,[0]*8
dla początkowych prawdopodobieństw, ponieważ liczby Ruby są zawsze „przekazywane przez wartość”Nie golfowany:
źródło
next X if Y
w zagnieżdżonych operatorach trójskładnikowych? Fajne znalezisko, możesz dodać go do porad Ruby!C #
418364 bajtówKompletny program C # oczekuje danych wejściowych od STDIN. Działa poprzez wczytywanie skał do tablicy wszystkich miejsc w rzece, skutecznie tworząc mapę, a następnie wykonuje 16 iteracji prawdopodobieństw przesunięcia wokół tablicy dziesiętnej o szerokości 8 przed wygenerowaniem wyniku.
Sformatowany kod:
źródło
for(;j-->0;)
). Można pozbyć się paru bohaterów choć zastępując ostatniC.WriteLine
przezC.Write
. Ponadto, jeśli użyjeszfloat
zamiast tegodecimal
, możesz zaoszczędzić kilka bajtów.decimal
ponieważfloat
nie będzie to precyzyjne, ale dziesiętna powinna wystarczyć na te problemy, ale prawdopodobnie może uciec od tego, jak mówisz. Wstawię,C.Write
jeśli uda mi się zagrać w golfa dalej, ponieważ jest to prawdopodobnie bliższe specyfikacji,C.WriteLine
ponieważ wydaje mi się, że 4 bajty nie wymagają edycji dla tego programu rozmiarów;)Haskell, 256 bajtów
Oto bardzo nie golfowa wersja wraz z kilkoma zastosowanymi sztuczkami:
Ostatnią sztuczką, jaką zastosowałem, było zwrócenie uwagi na to, że skały w jednym rzędzie są rzeczywiście oddzielone przez nieskończenie małą ilość. Innymi słowy, można zastosować transformator rozkładu prawdopodobieństwa dla każdej skały w tym samym rzędzie sekwencyjnie i w dowolnej kolejności, zamiast stosować je wszystkie jednocześnie. Działa to tylko dlatego, że problem uniemożliwia dwie poziomo sąsiadujące skały.
Tak więc program zamienia położenie każdej skały w transformator rozkładu prawdopodobieństwa, uporządkowany według współrzędnej y skały. Transformatory są następnie łączone w łańcuchy i stosowane do początkowego rozkładu prawdopodobieństwa. I to jest to!
źródło
Perl 169 bajtów
Czyta ze STDIN.
Całkiem prosto, domyślnie wykorzystuje kolumny -1 i 8, aby wygładzić przypadki graniczne. Prawdopodobieństwa można bezpiecznie przenosić na każdy następny poziom, ponieważ nie ma żadnych sąsiadujących kamieni, dlatego wystarczy jeden przebieg.
źródło
PHP, 358
Użycie siły mózgowej do ustalenia możliwych ścieżek i ich prawdopodobieństwa jest trudne i prawdopodobnie wymagałoby więcej kodu niż zwykła symulacja 1 000 000 wypadków na kajakach. Oh ludzkość!
Przykład:
Gra w golfa:
Ta wersja nie wykonuje żadnego ładnego wydruku i wyświetla prawdopodobieństwo pływakowego lądowania czółna w określonej pozycji.
źródło
PHP, 274
Nie umiem czytać / pisać GolfScript, aby uratować mi życie, ale zerknięcie na poddanie @ Howarda wskazało mi lepszy kierunek niż po prostu symulacja 1 miliona wypadków na kajakach.
Zaczynając od szeregu prawdopodobieństw dla pozycji początkowych, możemy po prostu podzielić te liczby za każdym razem, gdy napotkasz kamień.
Przykładowe dane wyjściowe:
Gra w golfa:
Przykładowy przebieg:
źródło
Haskell, 237
Mam tylko nadzieję, że kajak ma zainstalowany ghc ...
Sztuczka z nieskończoną listą została skradziona Mattowi Noonanowi, ku czci dla niego!
Mam nadzieję, że dobrze zrozumiałem logikę, ale przykład Matta
"5 4,4 1,5 5,3 3,6 2,9 4,12 3,13"
daje0.5613750000000001
i przykład OP"4 4,1 5,5 3,5"
daje0.49500000000000005
, co wydaje się poprawne, pomijając pewne błędy zmiennoprzecinkowe.Oto jest w akcji:
źródło