Nog een W3 PHP oefening die ik maar niet snap :-(
Zie deze oefening:
http://www.w3resource.com/php-exercises/php-function-exercise-3.php
Ik begrijp niet goed wat er gebeurd.
1. String lengte wordt berekend, 4 in dit geval
2. Else wordt uitgevoerd, want string length is niet 1
3. $n verminderd met 1, wordt 3
4. reverse string wordt uitgevoerd op '23'? Dan snap ik het niet meer.
Kan iemand het lijstje vervolledigen?
:-)
Okay, die vorige W3C oefening ging over arrays correct?
Als ik deze twee voorbeelden zie denk ik toch echt dat deze oefeningen een beetje brol zijn. Het uiteindelijke doel lijkt mij toch dat je inzicht verkrijgt over de werking van en het werken met arrays/functies?
Het eerste wat je zou moeten doen voordat je een functie gaat schrijven (in dit geval) is kijken of de functie of iets soortgelijks niet al toevallig bestaat. Een functie om een string om te draaien is er al. Ik vind het eerlijk gezegd een beetje een vreemde gang van zaken.
Als je besluit om voor een bepaalde technische oplossing te gaan moet je deze ook kunnen onderbouwen.
Misschien probeert W3C je in dit geval iets bij te brengen over functies die zichzelf aanroepen (zgn. recursieve functies)?
Een ander aspect van dit specifieke voorbeeld is wellicht dat je een string retourneert in plaats van dat je deze direct afdrukt. Dat is doorgaans handiger in het gebruik, in die zin dat je nog vrij bent in de keuze van wat je met deze return value doet (afdrukken of wellicht weer doorgeven aan iets anders).
Een functie (in zijn eenvoudigste verschijningsvorm) introduceer je doorgaans als je een bepaalde bewerking meer dan eens uitvoert en dat dit anders zou leiden tot duplicatie van code.
Bovenstaande aspecten over het (correct) gebruik van functies zijn interessant/leerzaam, dit specifieke voorbeeld van W3C ... not so much.
Let op: Dit is een recursieve function en geen standaard function.
substr($str1,1, $n) => substr($str1,1, 3) => begin met plaats 1 en 3 lang => 234
Dan weer opnieuw:
1. String lengte wordt berekend, 3 in dit geval
2. Else wordt uitgevoerd, want string length is niet 1
3. $n verminderd met 1, wordt 2
4. reverse string wordt uitgevoerd op '34'.
Nogmaals:
1. String lengte wordt berekend, 2 in dit geval
2. Else wordt uitgevoerd, want string length is niet 1
3. $n verminderd met 1, wordt 1
4. reverse string wordt uitgevoerd op '4'.
En dan:
1. String lengte wordt berekend, 1 in dit geval
2. If wordt uitgevoerd, want string length is 1
Verlaat de function met return $str1; Dat is dus return 4.
Dan gaat de vorige function aanroep weer verder waar die gebleven was.
En dat was op de regel met:
return reverse_string(substr($str1,1, $n)) . substr($str1, 0, 1);
Omgezet wordt dat:
return '4' . substr($str1, 0, 1);
En $str1 was daar '34' dus substr($str1, 0, 1); wordt '3'.
Dus nog verder omgezet krijg je:
return '4' . '3'; wordt return ''43';
Na deze return komt weer terug waar die gebleven was.
En dat was weer op de regel met:
return reverse_string(substr($str1,1, $n)) . substr($str1, 0, 1);
Enzovoort.
Gewijzigd op 17/07/2015 23:28:56 door - SanThe -
Echt.
Ik vind het nobel van je dat je dit helemaal uitschrijft SanThe maar deze functie stinkt gewoon haha. Ik bedoel: als je constateert dat de code gewoon brak is, dan is een verdere analyse eigenlijk overbodig.
Wat je dan meestal doet is de specificatie / gewenste werking gebruiken om iets beters te schrijven. Zelfde werking, andere (betere) implementatie.
En in dit geval is dat niet eens nodig, er is een native PHP functie hiervoor. Veel efficienter wordt het niet.
Deze oefening is grappig: het probeert je iets bij te brengen over functies terwijl "het punt" compleet gemist wordt :).
Deze function is inderdaad compleet overbodig.
Maar als je het principe snapt kan het wel leerzaam zijn.
Het is beslist niet voor beginners bedoeld.
Code (php)
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php
$test = 'Dit is een korte string met een beetje tekst erin yolo.';
function reverse_string($str1) {
$n = strlen($str1);
if($n == 1) {
return $str1;
} else {
$n--;
return reverse_string(substr($str1,1, $n)) . substr($str1, 0, 1);
}
}
$repeat = 100000;
$memory = memory_get_usage(true);
$time = microtime(true);
for ($i = 0; $i < $repeat; $i++) {
reverse_string($test);
}
$memory = memory_get_usage(true) - $memory;
$time = microtime(true) - $time;
echo '<h2>reverse_string</h2>time: '.(number_format($time, 3)).'s, memory: '.round($memory/1024, 0).' KB, peak: '.round(memory_get_peak_usage(true)/1024, 0).' KB<br />';
/* ************************ */
function reverse_string2($str) {
$ret = '';
for ($i=strlen($str)-1; $i > -1; $i--) {
$ret .= $str{$i};
}
return $ret;
}
$memory = memory_get_usage(true);
$time = microtime(true);
for ($i = 0; $i < $repeat; $i++) {
reverse_string2($test);
}
$memory = memory_get_usage(true) - $memory;
$time = microtime(true) - $time;
echo '<h2>reverse_string2</h2>time: '.(number_format($time, 3)).'s, memory: '.round($memory/1024, 0).' KB, peak: '.round(memory_get_peak_usage(true)/1024, 0).' KB<br />';
/* ************************ */
$memory = memory_get_usage(true);
$time = microtime(true);
for ($i = 0; $i < $repeat; $i++) {
strrev($test);
}
$memory = memory_get_usage(true) - $memory;
$time = microtime(true) - $time;
echo '<h2>strrev</h2>time: '.(number_format($time, 3)).'s, memory: '.round($memory/1024, 0).' KB, peak: '.round(memory_get_peak_usage(true)/1024, 0).' KB<br />';
?>
$test = 'Dit is een korte string met een beetje tekst erin yolo.';
function reverse_string($str1) {
$n = strlen($str1);
if($n == 1) {
return $str1;
} else {
$n--;
return reverse_string(substr($str1,1, $n)) . substr($str1, 0, 1);
}
}
$repeat = 100000;
$memory = memory_get_usage(true);
$time = microtime(true);
for ($i = 0; $i < $repeat; $i++) {
reverse_string($test);
}
$memory = memory_get_usage(true) - $memory;
$time = microtime(true) - $time;
echo '<h2>reverse_string</h2>time: '.(number_format($time, 3)).'s, memory: '.round($memory/1024, 0).' KB, peak: '.round(memory_get_peak_usage(true)/1024, 0).' KB<br />';
/* ************************ */
function reverse_string2($str) {
$ret = '';
for ($i=strlen($str)-1; $i > -1; $i--) {
$ret .= $str{$i};
}
return $ret;
}
$memory = memory_get_usage(true);
$time = microtime(true);
for ($i = 0; $i < $repeat; $i++) {
reverse_string2($test);
}
$memory = memory_get_usage(true) - $memory;
$time = microtime(true) - $time;
echo '<h2>reverse_string2</h2>time: '.(number_format($time, 3)).'s, memory: '.round($memory/1024, 0).' KB, peak: '.round(memory_get_peak_usage(true)/1024, 0).' KB<br />';
/* ************************ */
$memory = memory_get_usage(true);
$time = microtime(true);
for ($i = 0; $i < $repeat; $i++) {
strrev($test);
}
$memory = memory_get_usage(true) - $memory;
$time = microtime(true) - $time;
echo '<h2>strrev</h2>time: '.(number_format($time, 3)).'s, memory: '.round($memory/1024, 0).' KB, peak: '.round(memory_get_peak_usage(true)/1024, 0).' KB<br />';
?>
levert
Code (php)
1
2
3
4
5
6
2
3
4
5
6
reverse_string
time: 13.530s, memory: 0 KB, peak: 512 KB
reverse_string2
time: 1.718s, memory: 0 KB, peak: 512 KB
strrev
time: 0.046s, memory: 0 KB, peak: 512 KB
time: 13.530s, memory: 0 KB, peak: 512 KB
reverse_string2
time: 1.718s, memory: 0 KB, peak: 512 KB
strrev
time: 0.046s, memory: 0 KB, peak: 512 KB
YMMV, maar ja... We have a winner?
Is het schrijven van snelle / efficiënte functies een apart hoofdstuk op W3C? :)
EDIT: dit lijkt mij trouwens ook een verkeerd gebruik van recursie? :/
Gewijzigd op 17/07/2015 23:53:39 door Thomas van den Heuvel
Blij om te horen dat dit niet voor beginners is, ik vreesde al dat PHP niks voor mij was. :)
Deze W3C-oefening is echt: hoe kunnen we van iets simpels iets onnodig moeilijk en gecompliceerd maken?
PHP is echt wel te doen, ook voor jou ;)