Optymalizacja niepotrzebnych tablic w PHP

Załóżmy, że pewien programista ma zadanie znaleźć sumę liczb całkowitych od 1 do 100000000.

Nasz programista napisał eleganckie rozwiązanie tego zadania, o tak:

php<?php
  echo array_sum(range(1, 100000000));
?>

Piękne rozwiązanie, prawda? W jednej linii i tak dalej. Ale ono nie działa! Spróbuj uruchomić ten kod, a wyświetli się błąd o tym, że zażądałeś zbyt dużej ilości pamięci operacyjnej.

Hmm, 100000000 wydaje się nie tak dużo? Czy może dużo? Policzmy. Funkcja range tworzy tablicę z 100000000 liczbami. Załóżmy, że PHP przydziela na liczbę 2 bajty - wtedy do przechowania naszej tablicy będzie potrzebne 200000000 bajtów, czyli około 200 megabajtów pamięci operacyjnej.

Ale w rzeczywistości potrzeba będzie znacznie więcej pamięci operacyjnej z powodu bardzo dużych narzutów w PHP przy przechowywaniu tablicy. Na przykład, u mnie w tekście błędu wyświetla się, że próbuję przydzielić 4294967304 bajtów - około 4 gigabajtów!

Teraz jasne jest, dlaczego wyskakuje błąd - znacznie przekroczyliśmy dozwolony limit pamięci.

Nie jest trudno przepisać nasz skrypt na inny, praktycznie nie zużywający pamięci operacyjnej:

php<?php
  $sum = 0;
  
  for ($i = 1; $i <= 100000000; $i++) {
    $sum += $i;
  }
  
  echo $sum;
?>

A jeszcze lepiej użyjmy matematycznego rozwiązania:

php<?php
  $n = 1000000;
  $sum = $n * ($n + 1) / 2;
  echo $sum;
?>
Задание 1

Pewien programista miał zadanie znaleźć silnię podanej liczby. Rozwiązał je w następujący sposób:

php<?php
  $n = 100;
  echo array_product(range(1, $n));
?>

Wyjaśnij, co jest nie tak z tym kodem. Przerób kod na bardziej optymalny.

Задание 2

Pewien programista miał zadanie znaleźć liczbę cyfr, za pomocą których można zapisać wszystkie liczby całkowite od 1 do 1000000. Rozwiązał je w następujący sposób:

php<?php
  echo strlen(implode('', range(1, 1000000)));
?>

Wyjaśnij, co jest nie tak z tym kodem. Przerób kod na bardziej optymalny.

Задание 3

Pewien programista miał zadanie znaleźć liczbę liczb podzielnych bez reszty przez 7, znajdujących się w podanym przedziale. Rozwiązał je w następujący sposób:

php<?php
  $arr = [];
  
  for ($i = 0; $i <= 1000; $i++) {
    if ($i % 7 == 0) {
      $arr[] = $i;
    }
  }
  
  echo count($arr);
?>

Wyjaśnij, co jest nie tak z tym kodem. Przerób kod na bardziej optymalny.

Задание 4

Pewien programista miał zadanie znaleźć sumę dzielników liczby. Rozwiązał je w następujący sposób:

php<?php
  $num = 320;
  $divs = [];
  
  for ($i = 0; $i <= $num; $i++) {
    if ($num % $i == 0) {
      $divs[] = $i;
    }
  }
  
  echo array_sum($divs);
?>

Wyjaśnij, co jest nie tak z tym kodem. Przerób kod na bardziej optymalny.