--[ PHP Golf
Een nieuwe editie van PHP Golf! Het leeft weer!
--[ Wat is PHP Golf?
De bedoeling is een PHP script te maken met zo min mogelijk karakters.
Dus zo min mogelijk letters, nummers, spaties, newlines en dergelijke.
Met het script moet je een doelstelling bereiken.
We gaan ervan uit dat je de recenste PHP 5.x !!! versie hebt en standaard php.ini
configuratie. Tenzij anders vermeld.
(Standaard: register_globals = off)
Het script moet op UNIX-gebaseerde en Windows systemen werken.
--[ Voor wie is PHP Golf?
De competitie is voor iedereen toegankelijk.
--[ Inzendingen
Je kunt je oplossing sturen naar:
phpgolf [at] gmail.com
(Disclaimer: je e-mail zal niet worden gebruikt voor
spam of worden doorgegeven aan derden)
Het liefst heb ik de code in de body van de email, geen bijlage svp.
--[ Doelstelling
Je ontmoet wel eens leuke meiden waarvan jij je nummer wilt geven. Alleen is het veel
cooler als jij je nummer in woorden kan geven. Op meeste telefoons zitten de letters
op deze nummers:
0 => 0
1 => 1
2 => abc
3 => def
4 => ghi
5 => jkl
6 => mno
7 => pqrs
8 => tuv
9 => wxyz
Dus 0900-8844 (nummer van politie) kan 0Z00-TUIG worden en 09008844 wordt 0Z00TUIG. Nu is de bedoeling dat jij een script schrijft die alle mogelijkheden geeft wanneer je een telefoonnummer ingeeft. Elk mogelijke uitkomst moet worden weergeven op haar eigen regel.
Voorbeelden van geldige telefoonnummers:
06-12345678
0612345678
0900-8844
09008844
000-1234567
0001234567
Je mag er vanuit gaan dat de nummer uit $_GET komt met key 'nr' en dat deze altijd set is.
--[ Deadline:
De deadline is over 8 dagen.
Dinsdag 18:00 20 juni 2006
-----
Post in dit topic vragen/suggesties.
GEEN OPLOSSINGEN!
Mocht je een oplossing hebben, dan mag je gerust je karakter aantal posten.
Dit om andere te stimuleren ;)
Diegene die het minste karakters heeft gebruikt, wint!
Een telefoonnummer is in principe niet langer dan 10 cijfers, maar hier hoef je dat niet te valideren. Bij de golfs gaat het altijd om de functionaliteit en dat dan zo kort mogelijk.
E_ALL is niet standaard ingesteld in php.ini bij PHP 5.x. Het streepje blijft behouden en er mogen alleen letter combinaties, dus 0900-LOVE2PHP is niet geldig.
@Berry: in de vorige runs mocht je notices uitzetten. (EDIT: maar dat was php 4 en ik weet niett wat php 5's standaard php.ini instellingen zijn)
@Simon: valideren hoeft ook niet...
@Lennard: 'Elk mogelijke uitkomst moet worden weergeven op haar eigen regel.'
@Frits: nummer 3 was wat aan de grote kant, en heeft weinig success gehad.
*zucht wil ook meedoen* heeft er iemand een beetje tijd over? Mijn tijd is namelijk op.
Onzin dat een newline dan niet mogelijk is; een newline is precies wat het zegt, een nieuwe regel, en daarmee voldoe je imo aan het gestelde criterium. Dat een browser de output als HTML parsed en het dan anders weergeeft doet daar niets aan af, het criterium was niet dat de output HTML-formatted moest zijn dus je doet maar mooi view-source :P
--[Oplossingen
We beginnen met de inzending van Sandro, met 347 karakters.
[code]
<?php $n=''.$_GET['nr'];$p='ABCDEFGHIJKLMNOPQRSTUVWXYZ';$q=0;for($x=2;$x<=9;$x++)
{$z=3;if
($x==7||$x==9)$z=4;for($y=1;$y<=$z;$y++){$l[$x][$y]=$p{$q};$q++;}}function
x($p,$w=''){global
$n,$l;if(strlen($w)>=strlen($n))echo"$w<br>";
else{$c=substr($n,$p,1);
if(strpos('23456789',$c))
{foreach($l[$c]as$v){x($p+1,''.$w.$v);}}else
x($p+1,''.$w.$c);}}x(0);
[/code]?>
Een inzending die werkt, maar niet genoeg is voor de eerste plaats. Hier is meer creativiteit voor nodig. Een gouden tip voor volgende keer Sandro :)
Toch knap dat hij tot een oplossing is gekomen.
Ferry Hupse heeft een oplossing van 237 karakters.
[code]
<?$c=$_GET['nr'];$b=$c;$v=explode(" ","0 1 abc def ghi jkl mno pqrs tuv wxyz");$v["-"]="-";d(0);Function d($p)
{Global $v,$c,$b;$f=$v[$c{$p}];
For(;$a<strlen($f);$a++)
{$b{$p}=$f{$a};
If($p<strlen($c)-1)d($p+1);
Else echo"$b<br>";}return $b;}
[code]?>
Maar verbeterde later zich goed naar 211 karakters.
JeRa bleef mij maar volspammen met steeds kortere oplossing :)
Hij begon aanvankelijk met 229 karakters.
[code]
<?$l=strlen($n=$_GET[nr]);
$a=array('0','1',abc,def,ghi,jkl,mno,pqrs,tuv,wxyz,
'-'=>'-');
do{while($i<$l)$r[$i++]=0;$i--;$j=0;
while($j<$l)
echo $a[$n{$j}]{$r[$j++]};
echo "\n";while(++$r[$i]==strlen($a[$n{$i}])&&$i--);$i++;}
while($i);
[/code]?>
Zoals je misschien, een oneindige loop. Bij geen user input kun je al raden wat er gebeurt. Zo krijg ik ze het liefst aangevoerd, functioneel maar lelijk en te-erg-om-te-vertonen :)
Na meedere keren karakters afsnoepen, is hij uiteindelijk tot een oplossing van 188 chars gekomen.
Wat je misschien opmerkt is dat hij newline \n gebruikt. Dit is ook correct, zie topic post hierboven.
Roonaan is ook weer van de partij, met een 197 oplossing.
[code]
<? a($_GET[nr]);function a($a,$s=''){$z=array('0','1',ABC,DEF,GHI,JKL,MNO,PQRS,TUV,WXYZ,'-'=>'-');
if(!$a)
{echo"$s<br/>";return;}
for($i=0;$i<strlen($x=$z[$a{0}]);$i++){a(substr($a,1),
$s.$x{$i});}}?>
[/code]
Jammer is dat hij de laatste closing tag van PHP gebruikt, deze is niet nodig. Zonder deze was het een 195 oplossing geweest. Tip voor volgende keer :)
Er kan er maar een de beste zijn, alweer crisp! Dit keer met een grote marge, want hij heeft een oplossing van 174 tekens.
Petje af crisp. Ik heb zelf heel lang naar deze code gekeken, maar ik ben er nog niet helemaal uit. Zou je je code misschien kunnen uitleggen zodat anderen ook kunnen begrijpen wat jouw creativiteit heeft kunnen opbrengen? :)
Is toevallig ranzige code schrijven ook je beroep? :)
Crisp is weer de winnaar van een PHP Golf, gefeliciteerd!
Nee, ranzige code schrijven is niet mijn beroep; ik schrijf doorgaans hele nette code ;)
Ik denk dat je ook goed en netjes moet kunnen programmeren om ook iets heel ranzigs in elkaar te kunnen zetten; dat heeft alles te maken met inzicht in de taal en de mogelijkheden daarvan - iets wat alle inzenders zo te zien wel hebben :)
Ik zal vanavond een uitleg proberen te maken - was de stiekume reference je al opgevallen?
Ja, die was mij wel opgevallen maar waarom die daar staat is mij niet geheel duidelijk. Ik zie je uitleg wel verschijnen.
Verder ben ik met je eens dat je netjes moet kunnen programmeren om dit soort code te schrijven. Ook denk ik dat deelnemers met perl en/of javascript ervaring een voorsprong hebben op alleen PHP coders. De algemene PHP coder houdt zich hier helemaal niet bezig, in tegenstelling tot perl/js programmeurs. Natuurlijk ook enig creativiteit en het kennen van 'dustier corners' van PHP (ternary, string offset met {} etc)
Verder een algemene tip: systematisch te werk gaan is goed, maar daar win je geen golfs mee :)
Jemig wat ziet dat er knap uit. Ik had geen tijd om een werkend algoritme te bedenken. Ik kon nog net bedenken hoe je 0 en 1 niet vervangt.
En gelukkig is SuperRembo er nog om er wat foute dingen in te doen, want ik vond het best netjes. Maar ik heb het nog niet helemaal uitgeplozen, hiervoor zou ik wel een Zend studio willen hebben.
Ok, even wat uitleg. In de eerste plaats heb ik - net als JeRa - gekozen voor een iteratieve methode ipv een recursieve, globaal ziet zoiets er zo uit in nette code:
do
{
//-- print loopje
for ($i = 0; $i < count($a); $i++)
{
echo $a[$i][$p[$i]];
}
echo '<br>';
//-- volgende iteratie
for ($i = 0; $i < count($a); $i++)
{
//-- pointer ophogen
$p[$i]++;
if ($p[$i] == count($a[$i]))
{
//-- pointer resetten
$p[$i] = 0;
}
else
break;
}
}
while ($i < count($a));
?>
De truuk is nu natuurlijk om in ieder geval te proberen de printloop binnen de iteratieloop te krijgen, want 2 x dezelfde for-construct is een waste of precious bytes :P
Dan zit je nog met hoe te bepalen welke mogelijkheden er zijn voor een bepaald karakter; in feite zijn er alleen voor de cijfers 2 t/m 9 meerdere mogelijkheden, dus enkel voor die cijfers wil ik iets extra doen, en anders gewoon het cijfer zelf (of karakter in het geval van het minteken) in een var zetten; dat doe ik dus dmv $a=($a=$g{$i})>1?substr(ABC0DEF0GHI0JKL0MNO0PQRSTUV0WXYZ,$a*4-8,4):$a hetgeen korter is dan de array-varianten.
Checken of een string-index buiten de string valt doe je het best dmv >'' afvragen; alleen in die gevallen krijg je immers een lege string terug.
Last but not least is het gebruik van de reference $k=&$p[$i]. Vreemd, want $p komt verder nergens voor dus wat is dat dan? Well, dat is nou mijn pointerarray :) Het leuke is in PHP dat als $p of $p[$i] niet bestaat PHP die voor mij aanmaakt als ik ernaar refereer :) Geen initialisatie nodig dus. Het mooie is ook dat ik daarna $k kan gebruiken ipv $p[$i] wat weer de nodige bytes scheelt.
Voor de rest enkel de usual smerigheden zoals toewijzingen combineren met increments:
$k = 0&$j++; // increment $j en zet $k op 0
en dat weer conditioneel in een ternary:
$k=$j==$i++&&!$a{++$k}?0&$j++:$k
bovenstaande is eigenlijk wat het mogelijk maakt om de printloop met de iteratieloop te combineren :)