Wyzwanie:
Napisz program lub funkcję, która wprowadza liczbę dodatnią i zwraca jej silnię .
Uwaga: jest to pytanie trollujące kod . Proszę nie brać poważnie pytania i / lub odpowiedzi. Więcej informacji tutaj . Każde pytanie trollujące kod jest również pytaniem o popularność , więc wygrywa najwyższa odpowiedź.
popularity-contest
code-trolling
alephalpha
źródło
źródło
Odpowiedzi:
Jest to bardzo prosty numeryczny problem obliczeniowy, który możemy rozwiązać za pomocą przybliżenia Stirlinga :
Jak widać, ta formuła zawiera pierwiastek kwadratowy, który również będziemy potrzebować w przybliżeniu. Wybieramy do tego tak zwaną „metodę babilońską” , ponieważ jest ona prawdopodobnie najprostsza:
Pamiętaj, że obliczenie pierwiastka kwadratowego w ten sposób jest dobrym przykładem rekurencji.
Połączenie tego wszystkiego w programie Python daje nam następujące rozwiązanie twojego problemu:
Po prostej modyfikacji powyższy program może wygenerować porządną tabelę silni:
Ta metoda powinna być wystarczająco dokładna dla większości aplikacji.
źródło
DO#
Przykro mi, ale nie znoszę funkcji rekurencyjnej.
źródło
Jawa
źródło
Pyton
Oczywiście najlepszym sposobem rozwiązania dowolnego problemu jest użycie wyrażeń regularnych:
źródło
Haskell
Krótki kod jest wydajnym kodem, więc spróbuj tego.
Dlaczego trolling:
Śmiałbym się z każdego programisty, który to napisał ... Nieefektywność jest piękna. Prawdopodobnie również niezrozumiały dla żadnego programisty Haskell, który tak naprawdę nie potrafi napisać funkcji silni.
Edycja: Opublikowałem to jakiś czas temu, ale pomyślałem, że wyjaśnię przyszłym ludziom i ludziom, którzy nie potrafią czytać Haskell.
Kod tutaj bierze listę liczb od 1 do n, tworzy listę wszystkich permutacji tej listy i zwraca długość tej listy. Na moim komputerze 13 minut zajmuje około 20 minut. A potem powinno to zająć cztery godziny na 14! a potem dwa i pół dnia za 15! Tyle że w pewnym momencie zabrakło ci pamięci.
Edycja 2: W rzeczywistości prawdopodobnie nie zabraknie ci pamięci z powodu tego, że jest to Haskell (patrz komentarz poniżej). Być może będziesz w stanie zmusić go do oceny listy i zachować ją w pamięci, ale nie wiem wystarczająco dużo o optymalizowaniu (i nieoptymalizowaniu) Haskella, aby wiedzieć dokładnie, jak to zrobić.
źródło
[1..n]
. - Jedna szczególna permutacja[1..n]
, sprowadzona do thunk dla reszty permutacji (wielomian wn
). - Akumulator dlalength
funkcji.DO#
Ponieważ jest to problem matematyczny, do wykonania tych obliczeń warto użyć aplikacji zaprojektowanej specjalnie do rozwiązywania problemów matematycznych ...
Krok 1:
Zainstaluj MATLAB. Myślę, że wersja próbna będzie działać, ale ten bardzo skomplikowany problem jest prawdopodobnie wystarczająco ważny, aby zasługiwać na zakup pełnej wersji aplikacji.
Krok 2:
Dołącz składnik MATLAB COM do swojej aplikacji.
Krok 3:
źródło
DO#
Czynniki są operacjami matematycznymi wyższego poziomu, które mogą być trudne do strawienia za jednym razem. Najlepszym rozwiązaniem w takich problemach programistycznych jest rozbicie jednego dużego zadania na mniejsze zadania.
Teraz n! jest zdefiniowane jako 1 * 2 * ... * n, więc w zasadzie powtarzane mnożenie, a mnożenie jest niczym innym jak powtarzanym dodawaniem. Mając to na uwadze, następujące rozwiązanie rozwiązuje ten problem:
źródło
Trolle:
z = n - 1 + 1
) jest w rzeczywistości samo-dokumentujący, jeśli wiesz, co się dzieje.p[]
za pomocą rekurencyjnego obliczenia współczynników szeregowych!(To przybliżenie Lanczosa do funkcji gamma )
źródło
- 1 + 1
? Mój kompilator optymalizuje go (nie jest liczbą zmiennoprzecinkową, w której optymalizacja takiego kodu może być niebezpieczna), więc wydaje się niepotrzebna.double z = n - 1
jest częścią przybliżenia funkcji gamma. Pochodzi+ 1
ze związku, którygamma(n + 1) = n!
dla liczby całkowitej n.Wszyscy wiemy z uczelni, że najskuteczniejszym sposobem obliczenia mnożenia jest zastosowanie logarytmów. W końcu dlaczego ludzie mieliby używać tabel logarytmicznych przez setki lat?
Na podstawie tożsamości
a*b=e^(log(a)+log(b))
tworzymy następujący kod Python:Tworzy listę liczb od
1
dox
(+1
jest to potrzebne, ponieważ Python jest do bani), oblicza logarytm każdego z nich, sumuje liczby, podnosi e do potęgi sumy i ostatecznie zaokrągla wartość do najbliższej liczby całkowitej (ponieważ Python jest do bani) . Python ma wbudowaną funkcję obliczania silni, ale działa tylko dla liczb całkowitych, więc nie może generować dużych liczb (ponieważ Python jest do bani). Dlatego potrzebna jest powyższa funkcja.Btw, ogólna wskazówka dla studentów jest taka, że jeśli coś nie działa zgodnie z oczekiwaniami, to prawdopodobnie dlatego, że język jest do bani.
źródło
Niestety Javascript nie ma wbudowanej metody obliczania silni. Możesz jednak użyć jego znaczenia w kombinatorykach, aby ustalić wartość:
Silnia liczby n jest liczbą permutacji listy o tym rozmiarze.
Możemy więc wygenerować każdą listę liczby n-cyfrowej, sprawdzić, czy jest to permutacja, a jeśli tak, zwiększyć licznik:
Trolle:
O(n)
, nieO(n!)
, aleO(n^n)
. Już to wystarczyłoby, aby się tutaj zakwalifikować.number.toString(base)
, ale to nie działa dla baz powyżej 36. Tak, wiem 36! to dużo , ale wciąż ...Math.pow
? Nie? No cóż.++
poza pętlami for czyni go jeszcze bardziej tajemniczym. Jest też==
zły.$i
.new Array
,document.write
(z przyjaciółmi) ialert
(zamiast wiersz lub etykietę wejściowego) tworząc kompletny trifecta grzechów wyboru funkcji. Dlaczego mimo wszystko wkład jest dynamicznie dodawany?=
sprawiają, że są jeszcze trudniejsze do odczytania.źródło
Ruby and WolframAlpha
To rozwiązanie wykorzystuje interfejs API REST WolframAlpha do obliczania silni, RestClient pobiera rozwiązanie, a Nokogiri analizuje je. Nie wymyśla żadnych kół i wykorzystuje sprawdzone i popularne technologie, aby uzyskać wynik w najbardziej nowoczesny sposób.
źródło
JavaScript
JavaScript jest funkcjonalnym językiem programowania, co oznacza, że musisz używać funkcji do wszystkiego, ponieważ jest szybszy.
źródło
r = -~(function(){})
pewno to rozwiąże.Korzystanie z Bogo-Sort w Javie
To faktycznie działa bardzo powoli i nie jest dokładne dla wyższych liczb.
źródło
PERL
Silnia może być trudnym problemem. Technika mapowania / zmniejszania - podobnie jak Google - może podzielić matematykę, przerywając wiele procesów i zbierając wyniki. To dobrze wykorzysta wszystkie te rdzenie lub procesory w twoim systemie w mroźną zimową noc.
Zapisz jako f.perl i chmod 755, aby mieć pewność, że możesz go uruchomić. Masz zainstalowany Patologicznie Eklektyczny List Śmieci, prawda?
Trolle:
źródło
ARGV[0]
jest tak naprawdę pierwszym argumentem, a nie skryptem!$ARGV[0]
Pyton
Tylko algorytm O (n! * N ^ 2) do znalezienia silni. Obsługiwana skrzynka podstawowa. Brak przelewów.
źródło
Cóż, w Golfscript istnieje łatwe rozwiązanie. Możesz użyć interpretera Golfscript i uruchomić ten kod:
Spokojnie huh :) Powodzenia!
źródło
!
Matematyka
To nie wydaje się działać dla liczb większych niż 11, a silnia [11] zamroziła mój komputer.
źródło
Rubin
Najwolniejszy liniowiec, jaki mogę sobie wyobrazić. Obliczenie zajmuje procesorowi i7 2 minuty
6!
.źródło
Prawidłowym podejściem do tych trudnych problemów matematycznych jest DSL. Więc zamodeluję to pod kątem prostego języka
Aby ładnie napisać nasz DSL, pomocne jest wyświetlenie go jako wolnej monady generowanej przez funktor algebraiczny
Możemy to napisać w Haskell jako
Pozostawię czytelnikowi wyprowadzenie trywialnej implementacji
Teraz możemy opisać operację modelowania silni w tej DSL
Teraz, kiedy to modelowaliśmy, musimy po prostu zapewnić rzeczywistą funkcję interpretacyjną dla naszej darmowej monady.
Pozostałą część denotacji pozostawiam czytelnikowi.
Aby poprawić czytelność, czasami pomocne jest przedstawienie konkretnego AST formularza
a potem trywialna refleksja
a następnie rekursywna ocena AST jest łatwa.
źródło
Pyton
Poniżej znajduje się wersja rozwiązania w języku Python, która nie jest ograniczona do 32-bitowego (lub 64-bitowego w najnowszym systemie) limitu liczb całkowitych w Pythonie. Aby obejść to ograniczenie, użyjemy łańcucha jako danych wejściowych i wyjściowych dlafactorial
procedury i wewnętrznie podzielimy łańcuch na cyfry, aby móc wykonać mnożenie.Oto więc kod:
getDigits
funkcja dzieli ciąg reprezentujący liczbę na swoje cyfry, więc staje się „1234”[ 4, 3, 2, 1 ]
(odwrotna kolejność tylko upraszcza funkcjeincrease
imultiply
).increase
Funkcja przyjmuje taką listę i zwiększa się o jeden. Jak sama nazwa wskazuje,multiply
funkcja się zwielokrotnia, np.multiply([2, 1], [3])
Zwraca[ 6, 3 ]
ponieważ 12 razy 3 to 36. Działa to w taki sam sposób, jak pomnożysz coś za pomocą pióra i papieru.Następnie
factorial
funkcja wykorzystuje te funkcje pomocnicze do obliczenia faktycznej silni, na przykładfactorial("9")
podaje"362880"
jako wynik.Notatki
W Pythonie liczba całkowita nie ma limitu, więc jeśli chcesz to zrobić ręcznie, możesz to zrobić
Istnieje również bardzo wygodna
math.factorial(n)
funkcja.To rozwiązanie jest oczywiście o wiele bardziej skomplikowane, niż musi być, ale działa i faktycznie ilustruje, w jaki sposób można obliczyć silnię w przypadku ograniczenia przez 32 lub 64 bity. Więc chociaż nikt nie uwierzy, że jest to rozwiązanie, które wymyśliłeś dla tego prostego (przynajmniej w Pythonie) problemu, możesz się czegoś nauczyć.
źródło
Pyton
Najbardziej rozsądnym rozwiązaniem jest sprawdzenie wszystkich liczb, aż znajdziesz tę, która jest silnią podanej liczby.
źródło
Najbardziej eleganckie rozwiązanie rekurencyjne w C.
Każdy wie, że najbardziej eleganckie rozwiązania silni są rekurencyjne.
Factorial:
Ale mnożenie może być również definiowane rekurencyjnie jako kolejne dodawanie.
Mnożenie:
I tak można dodawać jako kolejne przyrosty.
Dodanie:
W
C
, możemy używać++x
i--x
obsługiwać operacje pierwotne(x + 1)
i(x - 1)
odpowiednio, więc mamy wszystko zdefiniowane.Wypróbujmy to:
Idealnie, chociaż 8! z jakiegoś powodu zajęło dużo czasu. No cóż, najbardziej eleganckie rozwiązania nie zawsze są najszybsze. Kontynuujmy:
Hmm, dam ci znać, kiedy wróci ...
źródło
Pyton
Jak wskazała odpowiedź @ Matt_Siekera, silnie można podzielić na dodatkowe - dlaczego rozkładanie zadań jest istotą programowania. Ale możemy podzielić to na 1!
Myślę, że ten kod gwarantuje błąd SO, ponieważ
Rekursja - rozgrzewa
Każda warstwa generuje połączenia w celu pomnożenia
który generuje wywołania do liczb dodatkowych
który generuje połączenia z addby1!
Za dużo funkcji, prawda?
źródło
Wystarczy wejść do Google i wpisać silnię:
http://lmgtfy.com/?q=5!
źródło
TI-Basic 84
To naprawdę działa :)
źródło
JavaScript
Oczywiście zadaniem programisty jest wykonanie jak najmniej pracy i wykorzystanie jak największej liczby bibliotek. Dlatego chcemy importować jQuery i math.js . Teraz zadanie jest proste:
źródło
Pyton
Po niewielkiej modyfikacji standardowej rekurencyjnej implementacji czynnikowej staje się ona niedopuszczalnie powolna dla n> 10.
źródło
Grzmotnąć
źródło
Spróbujmy to zrobić metodą Monte Carlo . Wszyscy wiemy, że prawdopodobieństwo równości dwóch losowych n- uprawnień wynosi dokładnie 1 / n! . Dlatego możemy po prostu sprawdzić, ile testów jest potrzebnych (nazwijmy ten numer b ), dopóki nie otrzymamy c trafień. Więc n! ~ b / c .
Sage, też powinien działać w Pythonie
źródło
grzmotnąć
Czynniki można łatwo ustalić za pomocą dobrze znanych narzędzi wiersza poleceń z bash.
Jak wspomniano w komentarzach @Aaron Davies, wygląda to na bardziej uporządkowane i wszyscy chcemy mieć ładny i uporządkowany program, prawda?
źródło
paste
polecenie:seq 1 $n | paste -sd\* | bc
paste
wygląda jak zwykłe angielskie słowo i łatwo je zapamiętać. Czy naprawdę tego chcemy? ; o)