... Ach, przepraszam, nie ma tu popcornu, tylko POPCNT.
Napisz najkrótszy program lub funkcję, która pobiera liczbę n
i wypisuje wszystkie liczby całkowite od 0 do 2 n - 1, w porządku rosnącym liczby 1 bitów w binarnej reprezentacji liczb (popcount). Duplikaty nie są dozwolone.
Kolejność liczb z tym samym popcount jest zdefiniowana w implementacji.
Na przykład dla n = 3
wszystkich tych danych wyjściowych są poprawne:
0, 1, 2, 4, 3, 5, 6, 7
[0, 4, 1, 2, 5, 3, 6, 7]
0 4 2 1 6 5 3 7
Format wejściowy i wyjściowy są zdefiniowane w implementacji, aby umożliwić korzystanie z funkcji językowych w celu dalszego kodowania kodu. Istnieje kilka ograniczeń dotyczących wyjścia:
- Liczby muszą być wyprowadzane w formacie dziesiętnym.
Dane wyjściowe muszą zawierać rozsądny separator między liczbami (dozwolony separator końcowy, ale nie wiodący).
Nowego wiersza (
\n
), zakładka (\t
), przestrzeń,,
,.
,;
,|
,-
,_
,/
są dość rozsądne separator. Nie mam nic przeciwko dodatkowym odstępom na ładne drukowanie, ale nie używam liter ani cyfr jako separatorów.- Liczby i separatory mogą być otoczone
[ ]
,{ }
lub dowolnej macierzy lub listy notacji. - Nie drukuj niczego, co nie zostało wymienione powyżej.
Premia
Pomnóż swój wynik przez 0,5, jeśli Twoje rozwiązanie może wygenerować liczbę w locie. Duch tej premii polega na tym, że jeśli chcesz bezpośrednio przekonwertować swoje rozwiązanie drukowania na generator, generator używa tylko co najwyżej pamięci O (n), gdzie n jest liczbą bitów, jak zdefiniowano powyżej. (Nie musisz tak naprawdę przekształcać swojego rozwiązania w generator). Zauważ, że chociaż narzucam n <= 28, pamięć potrzebna do przechowywania wszystkich liczb wciąż rośnie wykładniczo, a naiwne rozwiązanie sortujące pochłonie co najmniej 4 GB pamięci przy n = 28.
Przed skorzystaniem z tej premii proszę dodać proste wyjaśnienie dotyczące działania rozwiązania.
Odpowiedzi:
Pyth, 9 bajtów
o
rd przezs
um reprezentacji podstawy 2 (jN2
) w przedziale (U
) z2 ^ Q
.(
Q
=eval(input())
).Wypróbuj tutaj.
źródło
Python 2, 75 * 0,5 = 37,5
Wielokrotnie generuje następny najwyższy
v
z tym samym POPCOUNT przez ten algorytm kruszenia bitów .W rzeczywistości łatwiej było wygenerować je w malejącej liczbie pop, a następnie wydrukować uzupełnienie, aby zwiększyć. W ten sposób, a następnie
v
przelewa się2**n
, po prostu usuwamy wszystkie opróczn
bitów&N
gdzieN=2**n-1
, a to daje najmniejszą liczbę popcount 1. W ten sposób możemy wykonać tylko jedną pętlę. Nie ma chyba lepsze rozwiązanie, które bezpośrednio znajdzie następną mniejszą liczbę o tej samej POPCOUNT.Ze względu na problem z płotem musimy zacząć od
v=2**(n+1)-1
tego, aby operacja zakończyłav=N-1
się w pierwszej pętli.Dane wyjściowe dla
4
:źródło
console.log()
vsprint
). Może ta sztuczka jest zbyt ciężka.v=N-~N
J, 19 znaków, bez premii.
2 ^ y
- dwa do potęgiy
.i. 2 ^ y
- liczby całkowite od0
do(2 ^ y) - 1
.#: i. 2 ^ y
- każda z tych liczb całkowitych reprezentowanych w podstawie drugiej.+/"1 #: i. 2 ^ y
- sumy każdej reprezentacji(i. 2 ^ y) /: +/"1 #: i. 2 ^ y
- wektori. 2 ^ y
posortowany według kolejności elementów poprzedniego wektora, nasza odpowiedź.źródło
Python, 63 znaki
źródło
C 179 * 0,5 = 89,5
EDYCJA: 157 * 0,5 = 78,5
EDYCJA: 132 * 0,5 = 66
lub nieco ładniej sformatowany:
Co to robi?
oblicza ostatnią liczbę do wyświetlenia (pow (2, n) - 1)
zewnętrzna pętla przechodzi przez liczbę bitów (czyli od 0 do n-1), podczas gdy wewnętrzna pętla liczy tylko od 0 do m
Na x86 znajduje się instrukcja POPCNT, za pomocą której można policzyć ustawione bity. GCC i kompatybilne kompilatory mogą obsługiwać funkcję __builtin_popcount, która zasadniczo kompiluje się z tą instrukcją.
źródło
CJam, 13 bajtów
Dość prosta implementacja.
Jak to działa :
Wypróbuj online tutaj
źródło
Mathematica,
5046.
źródło
JavaScript (ES6) 41 (82 * 0,5)
Najprostszy sposób, w golfa
Bez golfa
Przetestuj w konsoli Firefox / FireBug
źródło
Bash + coreutils, 66
Jeden na początek:
źródło
sort
zajmuje to dużo czasu. Przy n = 28sort
konieczne będzie sortowanie 2 ^ 28 linii / ~ 13 GB danych.Haskell, (87 * 0,5) = 43,5
Przykład użycia:,
f 4
który wyprowadza[0,1,2,4,8,3,5,9,6,10,12,7,11,13,14,15]
Jak to działa: ani sortowanie, ani wielokrotne iterowanie po [0..2 ^ n-1] i szukanie liczb zawierających i 1s.
Funkcje
#
pomocnicze przyjmują dwa parametrya
ib
konstruują listę każdej liczby złożonej za
1 ib
0. Główna funkcjaf
wywołuje#
każdą kombinacjęa
ib
gdziea+b
jest równan
, zaczynając odn
zer i zer, aby uporządkować liczby. Dzięki lenistwu Haskella wszystkie te listy nie muszą być budowane całkowicie w pamięci.źródło
++
wa#b
oznaczałoby, że po lewej stronie (co może być duża) musi być wytwarzany w całości, a następnie skopiowane przed pierwsza pozycja w rezultacie jest produkowany, naruszając tym samym wymagania dotyczące premii?Ruby 47 znaków
Podobnie jak Python z @KeithRandall:
źródło
Mathematica, 26
Przykład:
źródło
Perl, 64/2 = 32
Po prostu powtarzaj
[0..2^n-1]
n + 1
czasy zakresu . W każdej iteracji wypisuj tylko liczby, które mają liczbę 1 bitów równą zmiennej iteracyjnej ($i
). Bity są liczone przez zliczanie1
(y/1//
) w liczbie zamienionej na ciąg binarny za pomocąsprintf
.Przetestuj mnie .
Perl, 63
Podejście do sortowania:
źródło
Java 8, 205
źródło
C ++ 11, 117 znaków:
Nie golfowany:
Wyjaśnienie:
Utwórz zestaw par int, int. Pierwsza int jest liczbą bitów, druga to liczba. Pary porównują się według pierwszego parametru, więc zestaw jest sortowany według liczby bitów.
źródło