<?php
/********** Generating sorted structure (array / SplMaxHeap): *************/
function generateSorted( $start = 300000 , $elementsNum = 10000 , $dev = 30 , $heap = false ) {
$sorted = $heap ?
new SplMaxHeap
( ) : array ( ) ; for ( $i = 1 ; $i <= $elementsNum ; $i ++ ) {
$start -= $rand ;
if ( ! $heap ) {
$sorted [ ] = $start ;
} else {
$sorted -> insert ( $start ) ;
}
}
return $sorted ;
}
/********************** Four insert functions: **************************/
// for loop, and array copying
function insert1( & $arr , $elem ) {
$arr [ ] = $elem ;
return true ;
}
$lastIndex = $c - 1 ;
$inserted = false ;
for ( $i = 0 ; $i < $c ; $i ++ ) {
if ( ! $inserted && $arr [ $i ] <= $elem ) {
$tmp [ ] = $elem ;
$inserted = true ;
}
$tmp [ ] = $arr [ $i ] ;
if ( $lastIndex == $i && ! $inserted ) $tmp [ ] = $elem ;
}
$arr = $tmp ;
return true ;
}
// new element inserted at the end of array
// and moved up until correct place
function insert2( & $arr , $elem ) {
for ( $i = $c ; $i > 0 ; $i -- ) {
if ( $arr [ $i - 1 ] >= $arr [ $i ] ) break ;
$tmp = $arr [ $i - 1 ] ;
$arr [ $i - 1 ] = $arr [ $i ] ;
$arr [ $i ] = $tmp ;
}
return true ;
}
// binary search for correct place + array_splice() to insert element
function insert3( & $arr , $elem ) {
$startIndex = 0 ;
$stopIndex = count ( $arr ) - 1 ; $middle = 0 ;
while ( $startIndex < $stopIndex ) {
$middle = ceil ( ( $stopIndex + $startIndex ) / 2 ) ; if ( $elem > $arr [ $middle ] ) {
$stopIndex = $middle - 1 ;
} else if ( $elem <= $arr [ $middle ] ) {
$startIndex = $middle ;
}
}
$offset = $elem >= $arr [ $startIndex ] ? $startIndex : $startIndex + 1 ;
}
// for loop to find correct place + array_splice() to insert
function insert4( & $arr , $elem ) {
$inserted = false ;
for ( $i = 0 ; $i < $c ; $i ++ ) {
if ( $elem >= $arr [ $i ] ) {
$inserted = true ;
break ;
}
}
if ( ! $inserted ) $arr [ ] = $elem ;
return true ;
}
/*********************** Speed tests: *************************/
// check if array is sorted descending
function checkIfArrayCorrect( $arr , $expectedCount = null ) {
if ( isset ( $expectedCount ) && $c != $expectedCount ) return false ; $correct = true ;
for ( $i = 0 ; $i < $c - 1 ; $i ++ ) {
if ( ! isset ( $arr [ $i + 1 ] ) || $arr [ $i ] < $arr [ $i + 1 ] ) { $correct = false ;
break ;
}
}
return $correct ;
}
// claculates microtimetime diff
function timeDiff( $startTime ) {
return $diff ;
}
// prints formatted execution time info
function showTime( $func , $time ) {
printf ( "Execution time of %s (): %f s\n " , $func , $time ) ; }
// generated elements num
$elementsNum = 10000 ;
// generate starting point
$start = 300000 ;
// generated elements random range 1 - $dev
$dev = 50 ;
echo "Generating array with descending order, $elementsNum elements, begining from $start \n " ;
$arr = generateSorted( $start , $elementsNum , $dev ) ;
showTime( 'generateSorted' , timeDiff( $startTime ) ) ;
$step = 2 ;
echo "Generating second array using range range(), $elementsNum elements, begining from $start , step $step \n " ;
$arr2 = range ( $start , $start - $elementsNum * $step , $step ) ; showTime( 'range' , timeDiff( $startTime ) ) ;
echo "Generating SplMaxHeap, $elementsNum elements, begining from $start \n " ;
$heap = generateSorted( $start , $elementsNum , $dev , true ) ;
showTime( 'SplMaxHeap' , timeDiff( $startTime ) ) ;
echo "Checking if array is correct\n " ;
$sorted = checkIfArrayCorrect( $arr , $elementsNum ) ;
showTime( 'checkIfArrayCorrect' , timeDiff( $startTime ) ) ;
if ( ! $sorted ) die ( "Array is not in descending order!\n " ) ; echo "Array OK\n " ;
// number of elements to insert from every range
$randElementNum = 20 ;
// some ranges of elements to insert near begining, middle and end of generated array
// start value => end value
300000 => 280000 ,
160000 => 140000 ,
30000 => 0 ,
) ;
foreach ( $ranges as $from => $to ) {
echo "Generating $randElementNum random elements from range [$from - $to ] to insert\n " ;
while ( count ( $values ) < $randElementNum ) { }
}
// some elements to insert on begining and end of array
echo "Generated elements: \n " ;
for ( $i = 0 ; $i < count ( $toInsert ) ; $i ++ ) { if ( $i > 0 && $i % 5 == 0 ) echo "\n " ;
printf ( "%8d , " , $toInsert [ $i ] ) ; if ( $i == count ( $toInsert ) - 1 ) echo "\n " ; }
// functions to test
$toTest = array ( 'insert1' => null , 'insert2' => null , 'insert3' => null , 'insert4' => null ) ; foreach ( $toTest as $func => & $time ) {
echo "\n \n ================== Testing speed of $func () ======================\n \n " ;
$tmpArr = $arr ;
for ( $i = 0 ; $i < count ( $toInsert ) ; $i ++ ) { $func ( $tmpArr , $toInsert [ $i ] ) ;
}
$time = timeDiff( $startTime ) ;
showTime( $func , $time ) ;
echo "Checking if after using $func () array is still correct: \n " ;
if ( ! checkIfArrayCorrect
( $tmpArr , count ( $arr ) + count ( $toInsert ) ) ) { echo "Array INCORRECT!\n \n " ;
} else {
echo "Array OK!\n \n " ;
}
//echo "Few elements from begining of array:\n";
//print_r(array_slice($tmpArr, 0, 5));
//echo "Few elements from end of array:\n";
//print_r(array_slice($tmpArr, -5));
//echo "\n================== Finished testing $func() ======================\n\n";
}
echo "\n \n ================== Testing speed of SplMaxHeap::insert() ======================\n \n " ;
for ( $i = 0 ; $i < count ( $toInsert ) ; $i ++ ) { $heap -> insert ( $toInsert [ $i ] ) ;
}
$time = timeDiff( $startTime ) ;
showTime( 'SplMaxHeap::insert' , $time ) ;
$toTest [ 'SplMaxHeap::insert' ] = $time ;
echo "\n \n ================== Functions time summary ======================\n \n " ;
foreach ( $toTest as $func => $time ) {
printf ( "%18s () => %.10f \n " , $func , $time ) ; }
PD9waHAKLyoqKioqKioqKiogR2VuZXJhdGluZyBzb3J0ZWQgc3RydWN0dXJlIChhcnJheSAvIFNwbE1heEhlYXApOiAqKioqKioqKioqKioqLwoKZnVuY3Rpb24gZ2VuZXJhdGVTb3J0ZWQoJHN0YXJ0ID0gMzAwMDAwLCAkZWxlbWVudHNOdW0gPSAxMDAwMCwgJGRldiA9IDMwLCAkaGVhcCA9IGZhbHNlKXsKCSRzb3J0ZWQgPSAkaGVhcCA/IG5ldyBTcGxNYXhIZWFwKCkgOiBhcnJheSgpOwoJZm9yKCRpID0gMTsgJGkgPD0gJGVsZW1lbnRzTnVtOyAkaSsrKXsKCQkkcmFuZCA9IG10X3JhbmQoMSwgJGRldik7CgkJJHN0YXJ0IC09ICRyYW5kOwoJCWlmKCEkaGVhcCl7CgkJCSRzb3J0ZWRbXSA9ICRzdGFydDsKCQl9ZWxzZXsKCQkJJHNvcnRlZC0+aW5zZXJ0KCRzdGFydCk7IAoJCX0KCX0KCXJldHVybiAkc29ydGVkOwp9CgovKioqKioqKioqKioqKioqKioqKioqKiBGb3VyIGluc2VydCBmdW5jdGlvbnM6ICoqKioqKioqKioqKioqKioqKioqKioqKioqLwoKLy8gZm9yIGxvb3AsIGFuZCBhcnJheSBjb3B5aW5nCmZ1bmN0aW9uIGluc2VydDEoJiRhcnIsICRlbGVtKXsKCWlmKGVtcHR5KCRhcnIpKXsKCQkkYXJyW10gPSAkZWxlbTsKCQlyZXR1cm4gdHJ1ZTsKCX0KCSRjID0gY291bnQoJGFycik7CgkkbGFzdEluZGV4ID0gJGMgLSAxOwoJJHRtcCA9IGFycmF5KCk7CgkkaW5zZXJ0ZWQgPSBmYWxzZTsKCWZvcigkaSA9IDA7ICRpIDwgJGM7ICRpKyspewoJCWlmKCEkaW5zZXJ0ZWQgJiYgJGFyclskaV0gPD0gJGVsZW0pewoJCQkkdG1wW10gPSAkZWxlbTsKCQkJJGluc2VydGVkID0gdHJ1ZTsKCQl9CgkJJHRtcFtdID0gJGFyclskaV07CgkJaWYoJGxhc3RJbmRleCA9PSAkaSAmJiAhJGluc2VydGVkKSAkdG1wW10gPSAkZWxlbTsKCX0KCSRhcnIgPSAkdG1wOwoJcmV0dXJuIHRydWU7Cn0KCi8vIG5ldyBlbGVtZW50IGluc2VydGVkIGF0IHRoZSBlbmQgb2YgYXJyYXkgCi8vIGFuZCBtb3ZlZCB1cCB1bnRpbCBjb3JyZWN0IHBsYWNlCmZ1bmN0aW9uIGluc2VydDIoJiRhcnIsICRlbGVtKXsKCSRjID0gY291bnQoJGFycik7CglhcnJheV9wdXNoKCRhcnIsICRlbGVtKTsKCWZvcigkaSA9ICRjOyAkaSA+IDA7ICRpLS0pewoJCWlmKCRhcnJbJGkgLSAxXSA+PSAkYXJyWyRpXSkgYnJlYWs7CgkJJHRtcCA9ICRhcnJbJGkgLSAxXTsKCQkkYXJyWyRpIC0gMV0gPSAkYXJyWyRpXTsKCQkkYXJyWyRpXSA9ICR0bXA7Cgl9CglyZXR1cm4gdHJ1ZTsKfQoKLy8gYmluYXJ5IHNlYXJjaCBmb3IgY29ycmVjdCBwbGFjZSArIGFycmF5X3NwbGljZSgpIHRvIGluc2VydCBlbGVtZW50CmZ1bmN0aW9uIGluc2VydDMoJiRhcnIsICRlbGVtKXsKCSRzdGFydEluZGV4ID0gMDsKCSRzdG9wSW5kZXggPSBjb3VudCgkYXJyKSAtIDE7CgkkbWlkZGxlID0gMDsKCXdoaWxlKCRzdGFydEluZGV4IDwgJHN0b3BJbmRleCl7CgkJJG1pZGRsZSA9IGNlaWwoKCRzdG9wSW5kZXggKyAkc3RhcnRJbmRleCkgLyAyKTsKCQlpZigkZWxlbSA+ICRhcnJbJG1pZGRsZV0pewoJCQkkc3RvcEluZGV4ID0gJG1pZGRsZSAtIDE7CgkJfWVsc2UgaWYoJGVsZW0gPD0gJGFyclskbWlkZGxlXSl7CgkJCSRzdGFydEluZGV4ID0gJG1pZGRsZTsKCQl9Cgl9Cgkkb2Zmc2V0ID0gJGVsZW0gPj0gJGFyclskc3RhcnRJbmRleF0gPyAkc3RhcnRJbmRleCA6ICRzdGFydEluZGV4ICsgMTsgCglhcnJheV9zcGxpY2UoJGFyciwgJG9mZnNldCwgMCwgYXJyYXkoJGVsZW0pKTsKfQoKLy8gZm9yIGxvb3AgdG8gZmluZCBjb3JyZWN0IHBsYWNlICsgYXJyYXlfc3BsaWNlKCkgdG8gaW5zZXJ0CmZ1bmN0aW9uIGluc2VydDQoJiRhcnIsICRlbGVtKXsKCSRjID0gY291bnQoJGFycik7CgkkaW5zZXJ0ZWQgPSBmYWxzZTsKCWZvcigkaSA9IDA7ICRpIDwgJGM7ICRpKyspewoJCWlmKCRlbGVtID49ICRhcnJbJGldKXsKCQkJYXJyYXlfc3BsaWNlKCRhcnIsICRpLCAwLCBhcnJheSgkZWxlbSkpOwoJCQkkaW5zZXJ0ZWQgPSB0cnVlOwoJCQlicmVhazsKCQl9Cgl9CglpZighJGluc2VydGVkKSAkYXJyW10gPSAkZWxlbTsKCXJldHVybiB0cnVlOwp9CgovKioqKioqKioqKioqKioqKioqKioqKiogU3BlZWQgdGVzdHM6ICoqKioqKioqKioqKioqKioqKioqKioqKiovCgovLyBjaGVjayBpZiBhcnJheSBpcyBzb3J0ZWQgZGVzY2VuZGluZwpmdW5jdGlvbiBjaGVja0lmQXJyYXlDb3JyZWN0KCRhcnIsICRleHBlY3RlZENvdW50ID0gbnVsbCl7CgkkYyA9IGNvdW50KCRhcnIpOwoJaWYoaXNzZXQoJGV4cGVjdGVkQ291bnQpICYmICRjICE9ICRleHBlY3RlZENvdW50KSByZXR1cm4gZmFsc2U7CgkkY29ycmVjdCA9IHRydWU7Cglmb3IoJGkgPSAwOyAkaSA8ICRjIC0gMTsgJGkrKyl7CgkJaWYoIWlzc2V0KCRhcnJbJGkgKyAxXSkgfHwgJGFyclskaV0gPCAkYXJyWyRpICsgMV0pewoJCQkkY29ycmVjdCA9IGZhbHNlOwoJCQlicmVhazsKCQl9Cgl9CglyZXR1cm4gJGNvcnJlY3Q7Cn0KLy8gY2xhY3VsYXRlcyBtaWNyb3RpbWV0aW1lIGRpZmYKZnVuY3Rpb24gdGltZURpZmYoJHN0YXJ0VGltZSl7CgkkZGlmZiA9IG1pY3JvdGltZSh0cnVlKSAtICRzdGFydFRpbWU7CglyZXR1cm4gJGRpZmY7Cn0KLy8gcHJpbnRzIGZvcm1hdHRlZCBleGVjdXRpb24gdGltZSBpbmZvCmZ1bmN0aW9uIHNob3dUaW1lKCRmdW5jLCAkdGltZSl7CglwcmludGYoIkV4ZWN1dGlvbiB0aW1lIG9mICVzKCk6ICVmIHNcbiIsICRmdW5jLCAkdGltZSk7Cn0KLy8gZ2VuZXJhdGVkIGVsZW1lbnRzIG51bQokZWxlbWVudHNOdW0gPSAxMDAwMDsKLy8gZ2VuZXJhdGUgc3RhcnRpbmcgcG9pbnQKJHN0YXJ0ID0gMzAwMDAwOwovLyBnZW5lcmF0ZWQgZWxlbWVudHMgcmFuZG9tIHJhbmdlICAxIC0gJGRldgokZGV2ID0gNTA7CgoKZWNobyAiR2VuZXJhdGluZyBhcnJheSB3aXRoIGRlc2NlbmRpbmcgb3JkZXIsICRlbGVtZW50c051bSBlbGVtZW50cywgYmVnaW5pbmcgZnJvbSAkc3RhcnRcbiI7CiRzdGFydFRpbWUgPSBtaWNyb3RpbWUodHJ1ZSk7CiRhcnIgPSBnZW5lcmF0ZVNvcnRlZCgkc3RhcnQsICRlbGVtZW50c051bSwgJGRldik7CnNob3dUaW1lKCdnZW5lcmF0ZVNvcnRlZCcsIHRpbWVEaWZmKCRzdGFydFRpbWUpKTsKCiRzdGVwID0gMjsKZWNobyAiR2VuZXJhdGluZyBzZWNvbmQgYXJyYXkgdXNpbmcgcmFuZ2UgcmFuZ2UoKSwgJGVsZW1lbnRzTnVtIGVsZW1lbnRzLCBiZWdpbmluZyBmcm9tICRzdGFydCwgc3RlcCAkc3RlcFxuIjsKJHN0YXJ0VGltZSA9IG1pY3JvdGltZSh0cnVlKTsKJGFycjIgPSByYW5nZSgkc3RhcnQsICRzdGFydCAtICRlbGVtZW50c051bSAqICRzdGVwLCAkc3RlcCk7CnNob3dUaW1lKCdyYW5nZScsIHRpbWVEaWZmKCRzdGFydFRpbWUpKTsKCmVjaG8gIkdlbmVyYXRpbmcgU3BsTWF4SGVhcCwgJGVsZW1lbnRzTnVtIGVsZW1lbnRzLCBiZWdpbmluZyBmcm9tICRzdGFydFxuIjsKJHN0YXJ0VGltZSA9IG1pY3JvdGltZSh0cnVlKTsKJGhlYXAgPSBnZW5lcmF0ZVNvcnRlZCgkc3RhcnQsICRlbGVtZW50c051bSwgJGRldiwgdHJ1ZSk7CnNob3dUaW1lKCdTcGxNYXhIZWFwJywgdGltZURpZmYoJHN0YXJ0VGltZSkpOwoKZWNobyAiQ2hlY2tpbmcgaWYgYXJyYXkgaXMgY29ycmVjdFxuIjsKJHN0YXJ0VGltZSA9IG1pY3JvdGltZSh0cnVlKTsKJHNvcnRlZCA9IGNoZWNrSWZBcnJheUNvcnJlY3QoJGFyciwgJGVsZW1lbnRzTnVtKTsKc2hvd1RpbWUoJ2NoZWNrSWZBcnJheUNvcnJlY3QnLCB0aW1lRGlmZigkc3RhcnRUaW1lKSk7CgppZighJHNvcnRlZCkgZGllKCJBcnJheSBpcyBub3QgaW4gZGVzY2VuZGluZyBvcmRlciFcbiIpOwplY2hvICJBcnJheSBPS1xuIjsKCiR0b0luc2VydCA9IGFycmF5KCk7CgovLyBudW1iZXIgb2YgZWxlbWVudHMgdG8gaW5zZXJ0IGZyb20gZXZlcnkgcmFuZ2UKJHJhbmRFbGVtZW50TnVtID0gMjA7CgovLyBzb21lIHJhbmdlcyBvZiBlbGVtZW50cyB0byBpbnNlcnQgbmVhciBiZWdpbmluZywgbWlkZGxlIGFuZCBlbmQgb2YgZ2VuZXJhdGVkIGFycmF5Ci8vIHN0YXJ0IHZhbHVlID0+IGVuZCB2YWx1ZQokcmFuZ2VzID0gYXJyYXkoCgkzMDAwMDAgPT4gMjgwMDAwLAoJMTYwMDAwID0+IDE0MDAwMCwKCTMwMDAwID0+IDAsCik7CmZvcmVhY2goJHJhbmdlcyBhcyAkZnJvbSA9PiAkdG8pewoJJHZhbHVlcyA9IGFycmF5KCk7CgllY2hvICJHZW5lcmF0aW5nICRyYW5kRWxlbWVudE51bSByYW5kb20gZWxlbWVudHMgZnJvbSByYW5nZSBbJGZyb20gLSAkdG9dIHRvIGluc2VydFxuIjsKCXdoaWxlKGNvdW50KCR2YWx1ZXMpIDwgJHJhbmRFbGVtZW50TnVtKXsKCQkkdmFsdWVzW210X3JhbmQoJGZyb20sICR0byldID0gMTsKCX0KCSR0b0luc2VydCA9IGFycmF5X21lcmdlKCR0b0luc2VydCwgYXJyYXlfa2V5cygkdmFsdWVzKSk7Cn0KLy8gc29tZSBlbGVtZW50cyB0byBpbnNlcnQgb24gYmVnaW5pbmcgYW5kIGVuZCBvZiBhcnJheQphcnJheV9wdXNoKCR0b0luc2VydCwgMzEwMDAwKTsKYXJyYXlfcHVzaCgkdG9JbnNlcnQsIC0xMDAwKTsKCmVjaG8gIkdlbmVyYXRlZCBlbGVtZW50czogXG4iOwpmb3IoJGkgPSAwOyAkaSA8IGNvdW50KCR0b0luc2VydCk7ICRpKyspewoJaWYoJGkgPiAwICYmICRpICUgNSA9PSAwKSBlY2hvICJcbiI7CglwcmludGYoIiU4ZCwgIiwgJHRvSW5zZXJ0WyRpXSk7CglpZigkaSA9PSBjb3VudCgkdG9JbnNlcnQpIC0gMSkgZWNobyAiXG4iOwp9Ci8vIGZ1bmN0aW9ucyB0byB0ZXN0CiR0b1Rlc3QgPSBhcnJheSgnaW5zZXJ0MScgPT4gbnVsbCwgJ2luc2VydDInID0+IG51bGwsICdpbnNlcnQzJyA9PiBudWxsLCAnaW5zZXJ0NCcgPT4gbnVsbCk7CmZvcmVhY2goJHRvVGVzdCBhcyAkZnVuYyA9PiAmJHRpbWUpewoJZWNobyAiXG5cbj09PT09PT09PT09PT09PT09PSBUZXN0aW5nIHNwZWVkIG9mICRmdW5jKCkgPT09PT09PT09PT09PT09PT09PT09PVxuXG4iOwoJJHRtcEFyciA9ICRhcnI7Cgkkc3RhcnRUaW1lID0gbWljcm90aW1lKHRydWUpOwoJZm9yKCRpID0gMDsgJGkgPCBjb3VudCgkdG9JbnNlcnQpOyAkaSsrKXsKCQkkZnVuYygkdG1wQXJyLCAkdG9JbnNlcnRbJGldKTsKCX0KCSR0aW1lID0gdGltZURpZmYoJHN0YXJ0VGltZSk7CglzaG93VGltZSgkZnVuYywgJHRpbWUpOwoJZWNobyAiQ2hlY2tpbmcgaWYgYWZ0ZXIgdXNpbmcgJGZ1bmMoKSBhcnJheSBpcyBzdGlsbCBjb3JyZWN0OiBcbiI7CglpZighY2hlY2tJZkFycmF5Q29ycmVjdCgkdG1wQXJyLCBjb3VudCgkYXJyKSArIGNvdW50KCR0b0luc2VydCkpKXsKCQllY2hvICJBcnJheSBJTkNPUlJFQ1QhXG5cbiI7Cgl9ZWxzZXsKCQllY2hvICJBcnJheSBPSyFcblxuIjsKCX0KCS8vZWNobyAiRmV3IGVsZW1lbnRzIGZyb20gYmVnaW5pbmcgb2YgYXJyYXk6XG4iOwoJLy9wcmludF9yKGFycmF5X3NsaWNlKCR0bXBBcnIsIDAsIDUpKTsKCQoJLy9lY2hvICJGZXcgZWxlbWVudHMgZnJvbSBlbmQgb2YgYXJyYXk6XG4iOwoJLy9wcmludF9yKGFycmF5X3NsaWNlKCR0bXBBcnIsIC01KSk7CgoJLy9lY2hvICJcbj09PT09PT09PT09PT09PT09PSBGaW5pc2hlZCB0ZXN0aW5nICRmdW5jKCkgPT09PT09PT09PT09PT09PT09PT09PVxuXG4iOwp9CgplY2hvICJcblxuPT09PT09PT09PT09PT09PT09IFRlc3Rpbmcgc3BlZWQgb2YgU3BsTWF4SGVhcDo6aW5zZXJ0KCkgPT09PT09PT09PT09PT09PT09PT09PVxuXG4iOwokc3RhcnRUaW1lID0gbWljcm90aW1lKHRydWUpOwpmb3IoJGkgPSAwOyAkaSA8IGNvdW50KCR0b0luc2VydCk7ICRpKyspewoJJGhlYXAtPmluc2VydCgkdG9JbnNlcnRbJGldKTsKfQokdGltZSA9IHRpbWVEaWZmKCRzdGFydFRpbWUpOwpzaG93VGltZSgnU3BsTWF4SGVhcDo6aW5zZXJ0JywgJHRpbWUpOwokdG9UZXN0WydTcGxNYXhIZWFwOjppbnNlcnQnXSA9ICR0aW1lOwplY2hvICJcblxuPT09PT09PT09PT09PT09PT09IEZ1bmN0aW9ucyB0aW1lIHN1bW1hcnkgID09PT09PT09PT09PT09PT09PT09PT1cblxuIjsKZm9yZWFjaCgkdG9UZXN0IGFzICRmdW5jID0+ICR0aW1lKXsKCXByaW50ZigiJTE4cygpID0+ICUuMTBmXG4iLCAkZnVuYywgJHRpbWUpOwp9