Dzisiaj przystąpiłam do zadania, które brzmiało:
“W dowolnym języku programowania wykonaj digital root dla liczby plus 5 testów sprawdzających kod”.
Tak wiem, dziwne mam rozrywki
Kodowanie było na czas więc nie przypadło mi to do gustu, jednak sam temat mnie zainteresował.
1.Digital Root
Wpierw należałoby się zapoznać z teorią. Co to digital root?
Digital root: jest to suma poszczególnych cyfr, które składają się na daną liczbę, do momentu, gdy otrzymamy cyfrę od 0 do 9.
Całkiem dobrze tematyka digital root wyjaśniona jest na Wolfram Math World. Możesz też skoczyć do przykładów w tym poście.
Zawody przegrałam . Na tym jednak nie poprzestałam. Ponieważ sam temat mnie zainteresował, zaczęłam się bawić. W piątkowy wieczór należy się trochę rozrywki każdemu
Napisałam trzy skrypty. Jeden w js
, drugi w php
i trzeci w py
. Do tego posta dołączę jeszcze 4 w ruby
dla porównania (ten w ruby został ułożony przez osobę, która zawody wygrała). Ogólnie w tych zawodach chodzi o to, by ułożyć w mniej niż 15 minut kod, który będzie jak najkrótszy. Liczy się czas, ale ważniejsza jest długość kodu.
I ta idea, ułożyć jak najkrótszy kod mi właśnie przyświecała.
Popatrzmy jakie kroki trzeba wykonać do obliczenia digital root:
graph TD
A(Input:<br/>Liczba jako String)-->B[Zsumuj wszystkie cyfry<br/>składające się na liczbę]
B-->C{Wynik jest<br/>jedną cyfrą?}
C.->|NIE|A
C.->|TAK|D(Wypisz wynik)
classDef decision fill:#fbfbd4,stroke:#444,stroke-width:1px
classDef inp fill:#f7f7f7,stroke:#444,stroke-width:1px
class A,D inp;
class C decision;
1.1.Przykład
1
2
3
//digital_root(941); // 9 + 4 + 2 = 14, 1 + 4 = 5
//digital_root(132189); // 1 + 3 + 2 + 1 + 8 + 9 = 24, 2 + 4 = 6
//digital_root(493193); // 4 + 9 + 3 + 1 + 9 + 3 = 29, 2 + 9 = 11, 1 + 1 = 2
Znamy już kroki przystąpmy do kodowania.
W zawodach daną wejściową był string i tego typu będę się trzymać w każdym kodzie.
.1.PHP
Wpierw kod w php
:
1
2
3
4
$n = '941'; //input
while (strlen($n) > 1) //loop until one digit
$n = array_sum(str_split($n)); //the magic sum
echo $n; //output
Całkiem fajnie prawda
W php
mamy gotową już funkcję, która wykona za nas całą operację na elementach tablicy array_sum
1 .
Dodatkowo php
jak widać ma gdzieś typy zmiennych 2 . Zmienna $n
jest stringiem, ale skoro chce je sumować to traktuje poszczególne elementy tablicy jako liczby. I tak do momentu aż zmienna $n
będzie jednocyfrowa.
Na wyjściu mamy też liczbę, można ją zamienić do stringa np. poprzez dołączenie pustego ciągu znaków .''
.
.2.Python
To teraz py
1
2
3
4
n='941'
while len(n) > 1:
n = str(sum(map(int,n)))
print(n)
Nie jest zbyt podobnie
Tutaj już interujemy po poszczególnych znakach/cyfrach zamieniając ich typ na int, a zwracając na wyjściu typ string.
Do sumowania elementów zastosowana jest konstrukcja, za którą uwielbiam Python’a. Składnia x for x in list if cond
jest jedną z najlepszych z jakimi się spotkałam 3. Niestety nie działa z while
.
.3.Ruby
Teraz porównanie z Ruby
1
2
3
4
5
n = gets
while n.length > 1
n = n.chars.map(&:to_i).sum.to_s
end
p n.to_i
W tym kodzie mogę podziwiać prostotę i przejrzystość. Nie znam Ruby
zbyt dobrze, jednak ten kod do mnie przemawia, jak bym czytała książkę: n.znaki.mapuj/interuj(zamień na integer).sumuj.konwerutj_do_stringa
.4.Javascript
1
2
3
4
let n = '941'
while(n.length > 1)
n = n.split``.reduce((a, b) => a * 1 + b * 1 + '')
console.log(n)
W tym kodzie zdecydowałam się na reduce
z tego względu, że na wejściu ma wynik poprzedniej operacji i aktualną wartość przy interacji, domyślnie na początku wchodzi z indeksem [0] i indeksem [1]. Wynikową reduce jest jedna liczba.
Powyższy kod stosuje pewne osobliwości języka js
2. Zresztą w php
można podobnie2.
Ja nazywam je hakami, ale świadczą one bardziej o słabym typowaniu zmiennych, ponieważ konwersja w js
i w php
stringa na liczbę może odbywać się poprzez string*1
, co w niektórych sytuacjach może prowadzić do błędów w przetwarzaniu kodu.
Dostępna jest w js
funkcja parseInt(string)
, z której powinno się korzystać, w php
zaś np. cast do typu zmiennej (int)string
. Ale, to tak na marginesie.
Konwersja zaś liczby na string w powyższym kodzie odbywa się poprzez +''
gdzie jest dostępna funkcja toSring(int)
, ale ile to znaków więcej .
Nie zmienia to faktu, że np. w Python
wykonanie podobnej operacji, czyli dodanie do liczby znaku, będzie skutkowało błędem:
TypeError: unsupported operand type(s) for +: ‘int’ and ‘str’
.5.Porównanie długości kodu
Zobaczmy w takim razie wyniki długości kodu (potraktowałam wszelkie odstępy pomiędzy znakami używane dla czytelności, jako zbędne - i dostanę za to pewnie od przyjaciela po głowie, że to nie po pythonowsku ):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//PYTHON=>44
console.log("Python",
`while len(n)>1:n=str(sum(map(int,n)))`.length)
//PHP => 48
console.log("PHP",
`while(strlen($n)>1)
$n=array_sum(str_split($n));`.length)
//RUBY =>51
console.log("Ruby",
`while n.length>1
n=n.chars.map(&:to_i).sum.to_s end`.length)
//JS=>54
console.log("Javascript",
`while(n.length>1)
n=n.split"".reduce((a,b)=>a*1+b*1+'')`.length)
//split`` powyżej powinno wyglądać tak, ale wolałam wstawić cudzysłów niż slashe
And the winner is: Python
Wpierw wydawało mi się, że wygra Ruby
lub php
, jednak po poprawieniu kodu zdecydowanie wygrywa py
.
I wydawało by się, że już nic z tego tematu nie można wyciągnąć więcej. Otóż, dokładnie, wydawałoby się.
.6.Math
Drążąc temat znalazłam równanie matematyczne, które w bardzo prosty i krótki sposób oblicza digital root. Całą teorię można przeczytać, wraz z warunkami na Wolfram Math World.
//math, obliczenie digital root
1+(n-1)%9
Nie na darmo się mówi już od starożytności, że Matematyka jest królową wszystkich nauk.
Krócej już się na pewno nie da
.7.Debugowanie i wyświetlanie
Używając wzoru matematycznego Ruby
akurat obejmie prym, jeśli do długości kodu wliczymy również wyświetlenie wyniku, dzięki skróconej opcji p
na print
Może należałoby się zastanowić, aby wprowadzić w innych językach jakieś skróty Zauważcie:
-
PHP:
var_dump
,print_r
,printf
,echo
. -
Python:
print
, -
Javascript:
console.log
- co jest najdłuższe, najbardziej wkurzające i wielu z nas układa sobie funkcję log do stososowania w swoim kodzie. - A Ruby ,
p
, po prostup
. I top
chciałabym zobaczyć we wszystkich językach tutaj wymienionych
1
p 1+(n-1)%9.to_i
Tym postem zapoczątkowałam nową kategorię na swoim blogu “Bitwy programowania” gdzie będę zamieszczać co ciekawsze zadania Notatki:
-
Języki
js
iphp
właśnie poprzez te osobliwości traktowane są jako słabotypowane, przez co niektórzy zajmujący się kodem uważają je jako języki gorsze. ↩ ↩2 ↩3 -
Stringi w pythonie są traktowane wewnętrznie jako lista charów. Można się do nich odnosić i interować poprzez index. Test:
a = 'tekst' print(*a) #result: t e k s t
↩