Ceylon, 1431 , 764 , 697 , 571 , 547 , 538 , 501 , 493 , 467 , 451
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.hash.get(b))1});}
Questo era l'originale, ungolfed:
Integer footprintCharacter(Integer b) {
return sum({0, for(i in 0..7) if(b.get(i)) 1 });
}
Integer footPrintString(String s) {
if(s == "test") {return 0;}
return sum({0, for(c in s) footprintCharacter(c.integer)});
}
shared void footprint() {
if(exists s = process.arguments[0]) {
print(footPrintString(s));
} else {
print("This program needs at least one parameter!");
}
}
Questo prende l'argomento da un parametro della riga di comando ... process.arguments è una sequenza (possibilmente vuota) di stringhe, quindi prima di usarne una, dobbiamo verificare se esiste realmente. Nell'altro caso viene emesso un messaggio di errore (ciò non è richiesto dalla domanda e verrà eliminato nelle prossime versioni).
La sum
funzione di Ceylon prende una Iterable non vuota di elementi di qualche tipo che deve soddisfare Summable
, cioè ha un plus
metodo, come Integer. (Non funziona con sequenze vuote perché ogni tipo di Summable avrà il suo zero e il runtime non ha alcuna possibilità di sapere quale si intende.)
Gli elementi di una stringa o i bit di un intero non sono iterabili non vuoti. Quindi stiamo usando qui la funzione per costruire un iterabile specificando alcuni elementi, quindi una "comprensione" (che verrà valutata a zero o più elementi). Quindi nel caso dei caratteri ne stiamo aggiungendo uno (ma solo quando è impostato il bit corrispondente), nel caso della stringa stiamo aggiungendo il risultato dei caratteri. (La comprensione sarà valutata solo quando la funzione di ricezione effettivamente scorre su di essa, non quando si costruisce l'Iterable.)
Vediamo come possiamo ridurlo. Innanzitutto, ciascuna delle funzioni viene chiamata solo in un punto, quindi possiamo incorporarle. Inoltre, come menzionato sopra, sbarazzarsi del messaggio di errore. (764 punti di impronta.)
shared void footprint() {
if (exists s = process.arguments[0]) {
if (s == "test") {
print(0);
} else {
print(sum({ 0, for (c in s) sum({ 0, for (i in 0..7) if (c.integer.get(i)) 1 }) }));
}
}
}
In realtà non abbiamo bisogno del nidificato interiore sum
, possiamo renderlo una grande comprensione. (Questo ci consente di risparmiare 37 punti di impronta per sum({0,})
, e alcuni di più per gli spazi bianchi, che verranno comunque eliminati alla fine.) 697:
shared void footprint() {
if (exists s = process.arguments[0]) {
if (s == "test") {
print(0);
} else {
print(sum({ 0, for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
}
}
Possiamo applicare un principio simile alla speciale "test"
stringa racchiusa : poiché in questo caso il risultato è 0 (ovvero non viene fornito alcun contributo alla somma), possiamo semplicemente farlo come parte della somma (ma dobbiamo invertire la condizione) . Questo ci consente principalmente di risparmiare print(0);
alcuni parentesi graffe e un mucchio di spazi di rientro, arrivando a un footprint di 571:
shared void footprint() {
if (exists s = process.arguments[0]) {
print(sum({ 0, if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
}
Facciamo lo stesso per il primo if
, con l'effetto collaterale che ora non viene fornito alcun argomento 0
invece di fare nulla. (Almeno ho pensato che sarebbe successo qui, invece sembra appendere con un ciclo eterno? Strano.)
shared void footprint() {
print(sum({ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
Possiamo effettivamente omettere il ()
per la sum
funzione qui, usando una sintassi di chiamata di funzione alternativa , che utilizza {...}
invece di ()
e riempirà le comprensioni in argomenti iterabili. Questo ha il footprint 538:
shared void footprint() {
print(sum{ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 });
}
Sostituendo il nome della funzione footprint
(40) con p
(3) si risparmiano altri 37 punti, portandoci a 501. (I nomi delle funzioni di Ceylon devono iniziare con caratteri minuscoli, quindi non possiamo ottenere meno di 3 punti qui.)
shared void p() {
print(sum{ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 });
}
Anche i nomi delle variabili s
(5) e c
(4), i
(4) non sono ottimali. Sostituiamoli con a
(argomento), d
(cifra?) E b
(bit-index). Footprint 493:
shared void p() {
print(sum{ 0, if (exists a = process.arguments[0]) if (a != "test") for (c in a) for (b in 0..7) if (c.integer.get(b)) 1 });
}
Non vedo alcuna ottimizzazione rimanente per gli spazi non bianchi, quindi rimuoviamo gli spazi bianchi non necessari (1 punto per ogni spazio, due per ciascuna delle due interruzioni di riga):
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.integer.get(b))1});}
Durante la navigazione dell'API, ho scoperto che Character.hash in realtà restituisce lo stesso valore del suo integer
attributo. Ma ha solo 14 punti invece di 30, quindi scendiamo a 451!
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.hash.get(b))1});}