Niekiedy w bitwach programowania nie ma opisu zadania. Są jedynie pokazane testy i należy na ich podstawie domyśleć się, co należy zrobić. Na poniższym zadaniu poległam. Do końca nie wiedziałam o co chodzi. Oczywiście po testach widziałam, że dotyczy ono różnego zapisu liczb. 15 minut jednak było zbyt krótkim czasem dla mnie, by znaleźć rozwiązanie. A okazało się banalne.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# TEST 1
INPUT: 15
OUTPUT: xfb1111o17
# TEST 2
INPUT: 0
OUTPUT: x0b0o0
# TEST 3
INPUT: 328
OUTPUT: x148b101001000o510
# TEST 4
INPUT: 831039
OUTPUT: xcae3fb11001010111000111111o3127077
Na powyższej podstawie należało podać kod, który przekształci liczbę w odpowiednio zakodowany ciąg. Dopiero po skończonej bitwie, kiedy można zobaczyć kod innych, o ile go udostępnią - dowiedziałam się o co chodziło. Rozłóżmy ten ciąg na czynniki pierwsze, składa się z cyfr i liter.
Najczęściej występującymi literami są: x, b i o. xfb1111o17, x0b0o0, x148b101001000o510, powtarzają się w każdym ciągu. x = HEX, b = BIN i o = OCT, co odpowiada zapisowi liczby w kodzie 16-szesnastkowym, 2-dwójkowym i 8-ósemkowym. Tak, jak ktoś wskaże rozwiązanie, wydaje się to tak oczywiste
JavaScript
Kod JS na rozwiązanie - kilka podejść. Ponieważ zawsze mamy jakiś wybór przy kodowaniu i kilka sposobów rozwiązania.
1
2
3
4
5
6
7
//z Map
n = 15;
k= [['x',16],['b',2],['o',16]];
console.log(k.map((a,b)=>a[0]+(n*1).toString(a[1])).join(''))
// OUTPUT: xfb1111o17
Niby założenie dobre, ale zastanówmy się. Tablica k
jest tak kiepsko napisana, że nie chciałabym jej zobaczyć w żadnym kodzie. Chcę użyć k = {'x':16,'b':2,'o':16}
. Powtórzmy powyższy kod, dostosowując go do danej wejściowej k
.
1
2
3
4
5
n = 15;
k = {'x':16,'b':2,'o':16}
console.log(Object.entries(k).map((a,b)=>a[0]+n.toString(a[1]+'')).join(''))
// OUTPUT: xfb1111o17
Object.entries(k)
tworzy dokładnie taką samą tablicę [['x',16],['b',2],['o',16]]
z obiektu {'x':16,'b':2,'o':16}
. Jak dla mnie jednak trochę za długo, jak na taką prostą oeprację. Chcemy interować po obiekcie k
więc po co przekształcać go na array
?
Kod do przepisania!
1
2
3
4
5
6
7
8
9
n=15;
s='';
k={x:16,b:2,o:8};
for(a in k){
s += a + n.toString(k[a])
}
console.log(s)
// OUTPUT: xfb1111o17
Szybciej prawda :) Tylko czy do tego zadania potrzebna nam jest loop’a.
1
2
n=15;
console.log(`x`+n.toString('16')+`b`+n.toString('2')+`o`+n.toString('8'));
Patrząc na całość, kod ze zwykłym loop na obiekcie, najbardziej do mnie przemawia.
Python
Zobaczmy Pythona, z zastosowaniem funkcji wbudowanych bin(), hex() i oct()
1
2
3
4
n=15
print('h'+hex(n)[-1:]+bin(n)+'o'+oct(n)[-1:])
# OUTPUT: xfb1111o17
Jak dla mnie to nie jest po pytonowsku, mimo, że w Python pisane Idea Pythona to prostota.
Wiedząc, że od wersji Pythona 3.6 wprowadzono nowy sposób formatowania liczb poprzez f{liczba:format}
powyższe możemy zapisać po prostu:
1
2
3
4
n=15
print(f'x{n:x}b{n:b}o{n:o}')
# OUTPUT: xfb1111o17
Teraz dla mnie jest po pythonowku. I to rozwiązanie przyjmuję
PHP
Czas na PHP. Wpierw z wykorzystaniem funkcji wbudowanych dechex()
, decbin()
i decoct()
1
2
3
4
5
$n=15;
echo "x".dechex($n)."b".decbin($n)."o".decoct($n);
// OUTPUT: xfb1111o17
Powyższy kod jest czytelny, ale za długi, na pewno da się napisać inaczej PHP z fromatowaniem:
1
2
3
4
5
$n=15;
printf("x%xb%bo%o",$n,$n,$n);
// OUTPUT: xfb1111o17
PHP, tak samo jak python
ma możliwość przedstawiania danych w odpowiednich formatach. Służą do tego różne funkcje printf()
, sprintf()
i jeszcze parę.
Niby wszystko jest poprawnie, ale denerwuje mnie powtórzenie trzy razy $n. Da się inaczej:
1
2
$n=15;
printf('x%1$xb%1$bo%1$o',$n);
Do printf()
możemy wchodzić z kilkoma argumentami, każdy otrzymuje swój numer. Wskazujemy go za pomocą albo liczby pożądkowej, jak w tym przypadku %1
, albo po jej formacie czyli dla liczby to %d
. Wszystko zależy jak ułożymy swój input. W tym przypadku użycie %d
będzie skutkowało błędem:
Warning: printf(): Too few arguments in […][…] on line xxx
Brrr, jest to najbardziej zaciemniona wersja w PHP .
Przejdźmy do zetsawienia długości:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// PYTHON No2 => 28
console.log(`print(f'x{n:x}b{n:b}o{n:o}')`.length)
// PHP No2 => 29
console.log(`printf("x%xb%bo%o",$n,$n,$n);`.length)
// PHP No3 => 29
console.log(`printf('x%1$xb%1$bo%1$o',$n);`.length)
// PYTHON No1 => 45
console.log(`print('h'+hex(n)[-1:]+bin(n)+'o'+oct(n)[-1:])`.length)
// PHP No1 => 50
console.log(`echo "x".dechex($n)."b".decbin($n)."o".decoct($n);`.length)
// JAVASCRIPT No3 => 69
console.log(`s='';k={x:16,b:2,o:8}for(a in k){s+=a+n.toString(k[a])}
console.log(s)`.length)
// JAVASCRIPT No4 => 74
console.log(`console.log('x'+n.toString('16')+'b'+n.toString('2')+
'o'+n.toString('8'));`.length)
// JAVASCRIPT No1 => 91
console.log(`k=[['x',16],['b',2],['o',16]];console.log(k.map((a,b)=>a[0]+(n*1)
.toString(a[1])).join(''))`.length)
// JAVASCRIPT No2 => 98 - o dziwo, choć kod jest ładniejszy
console.log(`k='x':16,'b':2,'o':16}console.log(Object.entries(k).map((a,b)=>a[0]
+n.toString(a[1]+'')).join(''))`.length)
W moim zestawieniu długości znów Python
wygrywa. Ma on przewagę nad PHP znów o jeden znak i pewnie trudno zgadnąć o który ;
Należy pamiętać, że w PHP mamy zapis zmiennych $
, co kod wydłuża, też o dodatkowy znak - wnioski pozostawiam do wyciągniecią samemu
Przygotowując po raz kolejny zestawienie, naszła mnie myśl, choć niektórzy się może obrażą na mnie. PHP jest badzo podobny do pythona. Przynajmniej w niektórych kwestiach.