C90 (gcc), 46 bajtów
r;main(c,v)int**v;{while(0<--c&*v[c])r++;c=r;}
Dane wejściowe są za pomocą argumentów wiersza poleceń (jedna liczba całkowita na argument), dane wyjściowe za pomocą kodu wyjścia .
Wypróbuj online!
Jak to działa
r jest zmienną globalną. Domyślny typ to int, a ponieważ jest globalny, domyślnie przyjmuje wartość 0 .
Argument funkcji c również domyślnie ma wartość int . Będzie zawierał liczbę całkowitą n + 1 dla tablic n booleanów; pierwszy argument main jest zawsze ścieżką do pliku wykonywalnego.
Argument funkcji v jest zadeklarowany jako int**
. Rzeczywistym typem v będzie char**
, ale ponieważ zbadamy tylko najmniej znaczący bit każdego argumentu, aby odróżnić znaki 0 (punkt kodowy 48 ) i 1 (punkt kodowy 49 ) od siebie, nie będzie to miało znaczenia dla little-endian maszyny
Pętla while zmniejsza wartość c i porównuje ją z wartością 0 . Gdy c osiągnie wartość 0 , wyrwiemy się z pętli. Jest to konieczne tylko wtedy, gdy tablica nie zawiera 0 „s.
Dopóki 0<--c
zwraca 1 , bierzemy c- ty argument wiersza poleceń ( v[c]
) i wyodrębniamy jego pierwszy znak, usuwając odwołanie ze wskaźnika ( *
). Bierzemy bitowe AND logicznej 0<--c
i punkt kodowy znaku (i trzy bajty śmieci po nim), więc warunek zwróci 0, gdy napotka się 0 , zrywając z pętli.
W pozostałym przypadku, gdy argumentami wiersza poleceń są 1 , r++
zwiększa r o 1 , licząc w ten sposób liczbę końcowych 1 .
Na koniec c=r
przechowuje obliczoną wartość r in c . Przy ustawieniach domyślnych kompilator optymalizuje i usuwa przypisanie; faktycznie generuje movl %eax, -4(%rbp)
instrukcję. Ponieważ ret
zwraca wartość rejestru EAX, generuje to pożądane wyjście.
Zauważ, że ten kod nie działa z C99, który zwraca 0 z main, jeśli osiągnięty jest koniec main .
01100
?