Dany:
- Liczbą naturalną S .
- Lista N racjonalnych wag W, które sumują się do 1.
Zwraca listę L N liczb całkowitych nieujemnych, takich jak:
(1) sum(L) = S
(2) sum((S⋅W_i - L_i)^2) is minimal
Innymi słowy, przybliżaj S⋅W_i
s liczbami całkowitymi tak dokładnie, jak to możliwe.
Przykłady:
1 [0.4 0.3 0.3] = [1 0 0]
3 [0 1 0] = [0 3 0]
4 [0.3 0.4 0.3] = [1 2 1]
5 [0.3 0.4 0.3] = [2 2 1] or [1 2 2] but not [1 3 1]
21 [0.3 0.2 0.5] = [6 4 11]
5 [0.1 0.2 0.3 0.4] = [1 1 1 2] or [0 1 2 2]
4 [0.11 0.3 0.59] = [1 1 2]
10 [0.47 0.47 0.06] = [5 5 0]
10 [0.43 0.43 0.14] = [4 4 2]
11 [0.43 0.43 0.14] = [5 5 1]
Zasady:
- Możesz w ogóle użyć dowolnego formatu wejściowego lub po prostu podać funkcję, która akceptuje dane wejściowe jako argumenty.
Tło:
Ten problem pojawia się, gdy wyświetla się S różnych rodzajów elementów w różnych proporcjach W i w odniesieniu do typów.
Innym przykładem tego problemu jest proporcjonalna reprezentacja polityczna, patrz paradoks podziału . Dwa ostatnie przypadki testowe znane są jako paradoks Alabama.
Jako statystyk rozpoznałem ten problem jako równoważny z problemem napotkanym przy identyfikacji wielkości próby podczas przeprowadzania próby warstwowej. W tej sytuacji chcemy, aby proporcja każdej warstwy w próbie była równa proporcji każdej warstwy w populacji. - @tomi
code-golf
number
arithmetic
glebm
źródło
źródło
round(A + B) != round(A) + round(B)
krótkie rozwiązanie wymaga wglądu w to, co się tutaj dzieje.L[i] - S*W[i]
kwadratów odległości , zamiast reguły 2 i zasady 3. To by było przybliżoneS*W[i]
.[0 1 2 2]
Jest też inne możliwe rozwiązanie dla5 [0.1 0.2 0.3 0.4]
Odpowiedzi:
APL, 21
To jest tłumaczenie z 37 bajtowej odpowiedzi CJam aditsu .
Przetestuj online .
Wyjaśnienie
źródło
Python 2,
9583132125143Mój pierwszy (i drugi) (i trzeci) algorytm miał problemy, więc po (innym!) Przepisaniu i kolejnych testach, oto (mam nadzieję) prawidłowe i szybkie rozwiązanie:
Źródło przed minifikatorem wygląda teraz:
Testy zwracają:
Ten algorytm jest podobny do innych odpowiedzi tutaj. Jest to O (1) dla num, więc ma ten sam czas działania dla liczb całkowitych 10 i 1000000. Teoretycznie jest to O (nlogn) dla liczby wag (z powodu sortowania). Jeśli to wytrzyma wszystkie inne trudne wejścia, zastąpi poniższy algorytm w moim zestawie narzędzi do programowania.
Nie używaj tego algorytmu do niczego, co nie jest golfem. Zrobiłem kompromis w szybkości, aby zminimalizować rozmiar źródła. Poniższy kod wykorzystuje tę samą logikę, ale jest znacznie szybszy i bardziej użyteczny:
Wartość num nie wpływa znacząco na prędkość. Przetestowałem to z wartościami od 1 do 10 ^ 19. Czas wykonania zmienia się liniowo wraz z liczbą wag. Na moim komputerze zajmuje to 0,15 sekundy przy obciążeniu 10 ^ 5 i 15 sekund przy obciążeniu 10 ^ 7. Zauważ, że wagi nie są ograniczone do ułamków, które sumują się do jednego. Zastosowana tutaj technika sortowania jest około dwa razy szybsza niż tradycyjny
sorted((v,i) for i,v in enumerate...)
styl.Oryginalny algorytm
To była funkcja w moim zestawie narzędzi, nieco zmodyfikowana dla golfa. Pochodzi z odpowiedzi SO . I to jest złe.
Podaje przybliżenie, ale nie zawsze jest poprawne, chociaż suma (outseq) == num jest zachowana. Szybki, ale niezalecany.
Dzięki @alephalpha i @ user23013 za wykrycie błędów.
EDYCJA: Ustaw totalw (d) na 1, ponieważ OP określa, że suma wag zawsze będzie wynosić 1. Teraz 83 bajty.
EDYCJA 2: Naprawiono błąd znaleziony dla [0.4, 0.3, 0.3], 1.
EDYCJA 3: Opuszczony wadliwy algorytm. Dodano lepszy.
EDIT4: To staje się śmieszne. Zastąpiony prawidłowym (tak naprawdę mam nadzieję) algorytmem.
EDYCJA 5: Dodano kod inny niż golfy dla innych, którzy mogą chcieć korzystać z tego algorytmu.
źródło
a([0.4, 0.3, 0.3], 1)
zwraca[0, 1, 0]
, a poprawną odpowiedzią jest[1, 0, 0]
.a([0.11,0.3,0.59],4)
powrócił[0, 1, 3]
. Powinno być[1, 1, 2]
.f([0.47,0.47,0.06],10)
powrócił[5, 4, 1]
. Powinno być[5, 5, 0]
.Mathematica,
67504645 znakówNie golfowany:
Przykład:
źródło
CJam - 37
Wypróbuj online
Wyjaśnienie:
Uwagi:
Inny pomysł - 46
Wypróbuj online
Jest to o wiele prostsze i wydajniejsze, ale niestety, nieco dłuższe. Chodzi o to, aby zacząć od L_i = floor (S * W_i), ustalić różnicę (powiedzmy D) między S i ich sumą, znaleźć wskaźniki D z największą ułamkową częścią S * W_i (sortując i biorąc górne D) i przyrost L_i dla tych wskaźników. Złożoność O (N * log (N)).
źródło
:e<
.JavaScript (ES6) 126
130 104 115 156 162 194Po wszystkich komentarzach i testach w odpowiedzi @ CarpetPython wróć do mojego pierwszego algorytmu. Niestety, inteligentne rozwiązanie nie działa. Wdrożenie zostało nieco skrócone, wciąż wypróbowuje wszystkie możliwe rozwiązania, oblicza kwadrat do kwadratu i utrzymuje minimum.
Edycja Dla każdego elementu wyjściowego o masie w „wszystkie” możliwe wartości to tylko 2: trunc (w * s) i trunc (w * s) +1, więc są tylko (2 ** elemensts) możliwe rozwiązania do wypróbowania.
Przetestuj w konsoli Firefox / FireBug
Wynik
To mądrzejsze rozwiązanie. Pojedynczy przebieg na tablicy wagowej.Dla każdego przejścia znajduję aktualną maksymalną wartość w. Zmieniam tę wartość w miejscu za pomocą ważonej wartości całkowitej (zaokrąglonej w górę), więc jeśli s == 21 i w = 0,4, otrzymamy 0,5 * 21 -> 10,5 -> 11. Przechowuję tę wartość zanegowaną, więc nie może znajdować się jako maksimum w następnej pętli. Następnie odpowiednio zmniejszam sumę całkowitą (s = s-11), a także zmniejszam sumę wag w zmiennej f.
Pętla kończy się, gdy nie można znaleźć maks. Powyżej 0 (wszystkie wartości! = 0 zostały zarządzane).
W końcu zwracam wartości zmienione ponownie na dodatnie. Ostrzeżenie: ten kod modyfikuje tablicę wag na miejscu, dlatego należy ją wywołać z kopią oryginalnej tablicy
Moja pierwsza próba
Nie takie inteligentne rozwiązanie. Dla każdego możliwego wyniku ocenia różnicę i utrzymuje minimum.
Niegolfowany i wyjaśniony
źródło
CJam, 48 bajtów
Proste rozwiązanie problemu.
Wejście idzie jak
Wyjaśnienie:
Wypróbuj online tutaj
źródło
Pyth: 40 bajtów
Definiuje funkcję
g
z 2 parametrami. Możesz to tak nazwaćMhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUHg5 [0.1 0.2 0.3 0.4
.Wypróbuj online: Pyth Compiler / Executor
Wyjaśnienie:
Stwarza to wszystkie możliwe rozwiązania
L
, gdzieL[i] = floor(S*W[i])
lubL[i] = floor(S*W[i]+1)
. Na przykład dane wejściowe4 [0.3 0.4 0.3
tworzą[[1, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 2], [2, 2, 1], [2, 1, 2], [1, 2, 2], [2, 2, 2]]
.[[2, 1, 1], [1, 2, 1], [1, 1, 2]]
Pozostań tylko .źródło
Mathematica 108
Wyjaśnienie
Nie golfił
IntegerPartitions[s,{Length@w},0~Range~s]
Zwraca wszystkie przegrody całkowitoliczbowejs
, przy użyciu elementów wykonanych z zestawu{0, 1, 2, ...s}
z ograniczeniem, że sygnał wyjściowy powinien zawierać taką samą liczbę elementów, jak w zestawie wag,w
.Permutations
podaje wszystkie uporządkowane układy każdej partycji całkowitej.{Tr[(s *w-#)^2],#}
zwraca listę uporządkowanych par{error, permutation}
dla każdej permutacji.Sort[...]
sortuje listę{{error1, permutation1},{error2, permutation2}...according to the size of the error.
[[1,2]]]
lubPart[<list>,{1,2}]
zwraca drugi element pierwszego elementu z posortowanej listy{{error, permutation}...}
. Innymi słowy, zwraca permutację z najmniejszym błędem.źródło
R,
858076Używa metody Hare Quota.
Usunięto parę po zobaczeniu specyfikacji, że W wyniesie 1
Testowe uruchomienie
źródło
Python,
139128117 bajtówPoprzednie rozwiązanie itertools, 139 bajtów
źródło
O(S^len(W))
rzeczywistości: P. Nowe rozwiązanie jest znacznie szybsze, ale wciąż powolneOktawa,
8776Gra w golfa:
Nie golfowany:
(Przeklęte „endfor” i „endfunction”! Nigdy nie wygrywam, ale lubię grać w golfa w „prawdziwym” języku).
źródło
zeros(size(w))
z0*w
.T-SQL,
167265Ponieważ lubię próbować wykonywać te wyzwania również w zapytaniu.
Zamieniono go w funkcję wbudowaną, aby lepiej pasowała do specyfikacji i utworzono typ danych tabeli. Trochę to kosztowało, ale to nigdy nie będzie rywalem. Każda instrukcja musi być uruchamiana osobno.
W użyciu
źródło