Скрипт, выполняемый на JavaScript за секунду, на PHP за 30 секунд проходит только 20%. В чём причина?

Начал изучать язык и для разминки решил написать на нём решение задачки из IQ теста.
1369647303_1518507562.jpg
Эту задачку уже решал на JavaScript:
for(a=1; a<10; a++)
for(b=1; b<10; b++)
for(c=1; c<10; c++)
for(d=1; d<10; d++)
for(e=1; e<10; e++)
for(f=1; f<10; f++)
for(g=1; g<10; g++)
for(h=1; h<10; h++)
for(j=1; j<10; j++)
    if( 100*d+10*g+j + 100*j+10*a+e + 100*b+10*h+f == 1000*d+100*d+10*a+b && 
        f*c/j == 10*g+a &&
        a!=b && a!=c && a!=d && a!=e && a!=f && a!=g && a!=h && a!=j &&
                b!=c && b!=d && b!=e && b!=f && b!=g && b!=h && b!=j &&
                        c!=d && c!=e && c!=f && c!=g && c!=h && c!=j &&
                                d!=e && d!=f && d!=g && d!=h && d!=j &&
                                        e!=f && e!=g && e!=h && e!=j &&
                                                f!=g && f!=h && f!=j &&
                                                        g!=h && g!=j &&
                                                                h!=j  )       
        alert(  " a="+a+
                " b="+b+
                " c="+c+
                " d="+d+
                " e="+e+
                " f="+f+
                " g="+g+
                " h="+h+
                " j="+j);

Просто вставлял в консоль браузера и через секунду появлялось решение.

Чуть-чуть адаптировал код под php, запустил, но через 30 секунд выполнение прервалось по таймауту.
То есть так и не найдя ответ.
Неужели PHP настолько медленнее работает по сравнению с JavaScript?!
Или Я где-то ошибся при перепечатывании на другой язык?
<?php
for($a=1; $a<10; $a++)
for($b=1; $b<10; $b++)
for($c=1; $c<10; $c++)
for($d=1; $d<10; $d++)
for($e=1; $e<10; $e++)
for($f=1; $f<10; $f++)
for($g=1; $g<10; $g++)
for($h=1; $h<10; $h++)
for($j=1; $j<10; $j++)
    if( 100*$d+10*$g+$j + 100*$j+10*$a+$e + 100*$b+10*$h+$f == 1000*$d+100*$d+10*$a+$b && 
        $f*$c/$j == 10*$g+$a &&
        $a!=$b && $a!=$c && $a!=$d && $a!=$e && $a!=$f && $a!=$g && $a!=$h && $a!=$j &&
                  $b!=$c && $b!=$d && $b!=$e && $b!=$f && $b!=$g && $b!=$h && $b!=$j &&
                            $c!=$d && $c!=$e && $c!=$f && $c!=$g && $c!=$h && $c!=$j &&
                                      $d!=$e && $d!=$f && $d!=$g && $d!=$h && $d!=$j &&
                                                $e!=$f && $e!=$g && $e!=$h && $e!=$j &&
                                                          $f!=$g && $f!=$h && $f!=$j &&
                                                                    $g!=$h && $g!=$j &&
                                                                              $h!=$j  )   
        echo    " a=",$a,
                " b=",$b,
                " c=",$c,
                " d=",$d,
                " e=",$e,
                " f=",$f,
                " g=",$g,
                " h=",$h,
                " j=",$j;
?>
  • Вопрос задан
  • 3686 просмотров
Пригласить эксперта
Ответы на вопрос 8
Adamos
@Adamos
А вам никто еще руки не оторвал за такой код? Привыкли, что за вас компиляторы думают?
Например, проверять $a != $b внутри десяти вложенных циклов - это [к сожалению, цензурных слов не нашлось].
Кстати, РНР проверяет условия по порядку, и ставить первым самое тяжелое - это [ну, скажем, саботаж...].
Ответ написан
Negwereth
@Negwereth
lvivcss.com.ua
Это не решение, это брутфорсище.
Ответ написан
Комментировать
latteo
@latteo
php можно ускорить в 2-3 раза, если сделать выход из циклов в последнем условии:
if( 100*$d+10*$g+$j + 100*$j+10*$a+$e + 100*$b+10*$h+$f == 1000*$d+100*$d+10*$a+$b && $f*$c/$j == 10*$g+$a) {
            echo " a=",$a, " b=",$b, " c=",$c, " d=",$d, " e=",$e, " f=",$f, " g=",$g, " h=",$h, " j=",$j;
            break 9;
          }


Ради фана переписал 2й алгоритм на Go
package main

import "fmt"
import "time"

func main() {
    st :=  time.Now().UnixNano()
    top:
    for a := 1; a<10; a++ {
      for b := 1; b<10; b++ {
        if b == a { continue; } else {
          for c := 1; c<10; c++ {
            if c==b || c==a { continue; } else {
              for d := 1; d<10; d++ {
                if  d==c || d==b || d==a { continue; } else {
                  for e := 1; e<10; e++ {
                    if e==d || e==c || e==b || e==a { continue; } else {
                      for f := 1; f<10; f++ {
                        if f==e || f==d || f==c || f==b || f==a { continue; } else {
                          for g := 1; g<10; g++ {
                            if g==f || g==e || g==d || g==c || g==b || g==a { continue; } else {
                              for h := 1; h<10; h++ {
                                if h==g || h==f || h==e || h==d || h==c || h==b || h==a { continue; } else {
                                  for j := 1; j<10; j++ {
                                    if j==h || j==g || j==f || j==e || j==d || j==c || j==b || j==a { continue; } else {
                                      if 100*d+10*g+j + 100*j+10*a+e + 100*b+10*h+f == 1000*d+100*d+10*a+b && f*c/j == 10*g+a {
                                        fmt.Println(" a=", a, " b=", b, " c=", c, " d=", d, " e=", e, " f=", f, " g=", g, " h=", h, " j=", j)
                                        break top
                                      }}}}}}}}}}}}}}}}}}
                
    elapsed := time.Now().UnixNano()
    delta := ( float64(elapsed) - float64(st) )/ 1e6
    fmt.Println("Время выполнения (ms): ", delta)
}


Ну и JS тоже разжился break`ом и профилированием
var time = performance.now();
// некий код
time = performance.now() - time;
console.log('Время выполнения (ms): ', time);

по времени в 2 раза медленне GO

Лучшие результаты на моей машине:
php - 600мс
js - 40мс
go - 20мс
Ответ написан
Pinsky
@Pinsky
Кофеиноникотиновая смесь в backend-код
JS оптимальнее работает с такими конструкциями потому что движок V8(а Вы скорее всего на нем и тестили) - старается максимально оптимизировать данные вычисления.

PHP - не лучший язык для подобных задач. У PHP есть свои сильные стороны, но решение подобных задач, подобным методом - не они
Ответ написан
iCoderXXI
@iCoderXXI
React.JS/FrontEnd engineer
Короче говоря херню ты написал, друже. вот оптимизированный код, отрабатывает за пару секунд.

<?php
  for($a=9; $a>=1; $a--) {
    $a10 = 10*$a;

    for($b=9; $b>=1; $b--) {
      if ($a===$b) continue;
      $b100 = 100*$b;

      for($c=9; $c>=1; $c--) {
        if ($a===$c || $b===$c) continue;

        for($d=9; $d>=1; $d--) {
          if ($a===$d || $b===$d || $c===$d) continue;
          $d100 = 100*$d;
          $v2 = 1000*$d+$d100+$a10+$b;

          for($e=9; $e>=1; $e--) {
            if ($a===$e || $b===$e || $c===$e || $d===$e) continue;

            for($f=9; $f>=1; $f--) {
              if (
                $a===$f || $b===$f || $c===$f ||
                $d===$f || $e===$f
              ) continue;
              $fc=$f*$c;

              for($g=9; $g>=1; $g--) {
                if (
                  $a===$g || $b===$g || $c===$g ||
                  $d===$g || $e===$g || $f===$g
                ) continue;
                $g10 = 10 * $g;
                $g10a = $g10+$a;

                for($h=9; $h>=1; $h--) {
                  if (
                    $a===$h || $b===$h || $c===$h ||
                    $d===$h || $e===$h || $f===$h || $g===$h
                  ) continue;
                  $v3 = $b100+10*$h+$f;

                  for($j=9; $j>=1; $j--) {
                    if (
                      $a===$j || $b===$j || $c===$j || $d===$j ||
                      $e===$j || $f===$j || $g===$j || $h===$j
                    ) continue;

                    if(
                      $d100+$g10+$j + 100*$j+$a10+$e + $v3 === $v2
                      && $fc/$j === $g10a
                    ) {
                      echo  "\n a=",$a,
                            " b=",$b,
                            " c=",$c,
                            " d=",$d,
                            " e=",$e,
                            " f=",$f,
                            " g=",$g,
                            " h=",$h,
                            " j=",$j,"\n\n";
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }


Если вдруг не понял что к чему, объясняю, у тебя вложено друг в друга 9 циклов от 1 до 10, таким образом получается 10^9 итераций, т.е. миллиард. И ты все условия и вычисления упихал в самый внутренний цикл, и производишь их миллиард раз, причем в 95% ситуаций вообще в холостую. Я вынес все проверки и вычисления максимально наружу, насколько это позволяет логика, таким образом 95% итераций, холостых вычислений и пр. мусора просто не выполняется в принципе. Поэтому код теперь отрабатывает быстро, как и должен.
Ответ написан
cah_ek
@cah_ek Автор вопроса
Получается, насколько понял,
JavaScript работает быстрее php только в Хроме за счёт V8 (исправленный код выполняется просто мгновенно),
PHP исполняет исправленный код секунды за две.
JavaScript в Firefox выполняется секунд 12.
Ответ написан
@ZoomLS
PHP всегда был медленным, JS конечно же быстрее.
Но тут пошли сравнения с движками браузеров, правильнее брать node.js в данном случае. А то php на сервере выполняется, а js - на клиенте. Как-то неправильно так сравнивать.
Ответ написан
Bobsans
@Bobsans
Full-Stack Developer
Чет интересно даже стало))
Вот мое решение:
func gen() [][]int {
	res := [][]int{}
	for f := 0; f < 10; f++ {
		for c := 0; c < 10; c++ {
			if c == f { continue }
			for j := 1; j < 10; j++ {
				if j == f || j == c { continue }
				x := int(f * c / j)
				g := int(x / 10)
				a := x % 10
				if f != g && f != a && c != g && c != a && j != g && j != a && g != a && 100 > f * c/j && f * c/j > 9 && f * c%j == 0 {
					res = append(res, []int{f, c, j, g, a})
				}
			}
		}
	}
	return res
}

func calc() {
	items := gen()
top:
	for d := 0; d < 10; d++ {
		for e := 0; e < 10; e++ {
			if e == d { continue }
			for b := 0; b < 10; b++ {
				if d == b || e == b { continue }
				for h := 0; h < 10; h++ {
					if d == h || e == h || b == h { continue }
					for _, item := range items {
						if d*100+item[3]*10+item[2]+ item[2]*100+item[4]*10+e+ b*100+h*10+item[0]==d*1000+d*100+item[4]*10+b {
							if item[0] != b && item[0] != d && item[0] != e && item[0] != h &&
								item[1] != b && item[1] != d && item[1] != e && item[1] != h &&
								item[2] != b && item[2] != d && item[2] != e && item[2] != h &&
								item[3] != b && item[3] != d && item[3] != e && item[3] != h &&
								item[4] != b && item[4] != d && item[4] != e && item[4] != h {
								fmt.Println("a =", item[4], " b =", b, " c =", item[1], " d =", d, " e =", e, " f =", item[0], " g =", item[3], " h =", h, " j =", item[2])
								break top
							}
						}
					}
				}
			}
		}
	}
}

st := time.Now().UnixNano()
calc()
fmt.Println("Время выполнения (ms): ", (float64(time.Now().UnixNano()) - float64(st)) / 1e6)

# a = 4  b = 6  c = 9  d = 1  e = 5  f = 8  g = 2  h = 7  j = 3
# Время выполнения (ms):  0.498432
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы