«phpClub» — архив тем ("тредов"), посвящённых изучению PHP и веб-технологий.
Аноним 2021/04/17 11:49:34  №1999047 1
пук.jpg (51, 1080x531)
531x1080
Меня затрахали нерешаемые моим мозгом бонусные задачи из учебника, что делать?
Ответы: >>1999073 >>1999079
Аноним 2021/04/17 12:11:23  №1999073 2
>>1999047
Скорее всего ты чего-то недогнал в процессе обучения. Тут не работает как в школе\шараге и надо честно позадрачивать с недельку.
На чём всрался?
Ответы: >>1999103
Аноним 2021/04/17 12:13:26  №1999079 3
>>1999047

Ты можешь запостить свой код, и написать, что именно непонятно. Также, можно попробовать поискать решение задачи в гугле.
Ответы: >>1999103
Аноним 2021/04/17 12:29:36  №1999103 4
1522495958120494646.jpg (136, 1080x971)
971x1080
>>1999073
>>1999079
Да че я не догнал... Все задачи решил предыдущие, но если попросить здесь помощи по бонусным мне в сотый раз льют в уши кучу помоев, которые никак не помогают решить задачу.

https://ideone.com/kzN6Eh

Вот тут например, спросил как пофиксить задачу, сказали вместо ничего выводить пробел)0 Да я как бы и так знаю в чем проблема, а как это сделать нахуй?))) Очень информативно.

Про банкомат задачу тоже как не знал как решать, так и не знаю. Высрали про какой-то последовательный перебор, но я отказываюсь понимать это.

Я в центре на пикрелейтеде, inb4 я долбоеб неблагодарный и не ценю помощь, нахуй из треда


Ответы: >>1999380 >>1999639
Аноним 2021/04/17 15:41:27  №1999380 5
Ответы: >>1999814
Аноним 2021/04/17 19:26:34  №1999639 6
>>1999103

Ты ничего не переспросил в ответ на совет выводить пробел, вот тебе ничего больше и не посоветовали.

У тебя есть переменная $i, которая указывает, какую по счету букву надо взять из строки $value. Но некоторые строки слишком короткие и в них нет $i-й буквы. Надо проверять, что $i меньше чем длина $value (mb_strlen). Если это так, то берем одну букву из $value и добавляем в $letter. Если это не так ($i >= длины строки), то надо в $letter добавлять пробел.

Если с этим все стало понятно, то вот еще совет: у тебя используется рекурсия (функция abc вызывает саму себя). Можно заменить ее на цикл for, где $i меняется от 0 до максимальной длины строки стихотворения. Сейчас эта макс. длина у тебя вписана как 33, но лучше вычислять ее: разбить стих на строки, затем преобразовать массив строк в массив длин с помощью array_map, затем взять максимальную длину с помощью max().

> последовательный перебор

Это у многих вызывает сложность. Почему бы не попробовать начать с более простой подзадачи. Допустим, у нас есть всего 2 вида купюр - по 500 и по 100. Допустим, у тебя есть функция next(), и ей дается на вход 2 массива:

- первый массив - это общее количество купюр в банкомате вида [5, 2]. Это значит, что есть 5 купюр по 500 и 2 по 100.
- второй массив - это какая-то произвольная комбинация купюр, например [2, 1] то есть 2x500 + 1x100.

Функция должна вернуть следующую за данной комбинацию (в виде массива). Если ей дали 2x500 + 1x100, она должна вернуть 2x500 + 2x100 (то есть массив [2, 2]). Если ей дали 2x500 + 2x100, она должна вернуть 3x500 + 0x100 (так как 3 купюры по 100 быть не может).

То есть, функция получает информацию о запасе купюр и одну комбинацию, и должна вернуть следующую за ней комбинацию (которая дает чуть-чуть большую сумму).

Уточняй, если что непонятно.
Ответы: >>2000963 >>2002365
Аноним 2021/04/18 00:18:45  №1999814 7
>>1999380
На хуй отправляешься.
Аноним 2021/04/19 03:45:56  №2000963 8
>>1999639
>Ты ничего не переспросил в ответ на совет выводить пробел, вот тебе ничего больше и не посоветовали.
У меня взорвалось очко от того что на более сложные задачи мне дают такие неинформативные ответы. Наверное, я не прав, что так грубо выражаюсь, спасибо за помощь.
Аноним 2021/04/20 11:09:59  №2002365 9
>>1999639
>Функция должна вернуть следующую за данной комбинацию (в виде массива). Если ей дали 2x500 + 1x100, она должна вернуть 2x500 + 2x100 (то есть массив [2, 2]). Если ей дали 2x500 + 2x100, она должна вернуть 3x500 + 0x100 (так как 3 купюры по 100 быть не может).

https://ideone.com/KWu2kP

Ответы: >>2002397 >>2002413
Аноним 2021/04/20 11:37:06  №2002397 10
>>2002365
Смотрю на ваши задачки и тоже хочется что-то мелкое попилить.
А приходится шатать легаси на пол ляма строк...
Аноним 2021/04/20 11:52:52  №2002413 11
>>2002365

Начиная с PHP5.4, можно вместо array() писать [], это компактней.

Еще, вместо сравнения массивов по одному элементу, можно сравнивать массивы целиком с помощью == или ===, подробности (не очень подробные) в мануале: https://www.php.net/manual/ru/language.operators.array.php

Хорошо, для 2 номиналов задача решена. Теперь надо переделать функцию, чтобы она работала не с 2 номиналами, а с произвольным количеством номиналов. То есть, массивы могут быть произвольного размера.

Так как количество номиналов неизвестно заранее, мы не можем просто вписать нужное количество блоков if. Нам придется сделать цикл, в котором мы идем от конца массива (самой маленькой купюры) к началу (самой большой купюре). На каждом шаге мы увеличиваем текущий элемент на 1. Если он получился меньше, чем запас данной купюры, то цикл заканчивается. Иначе, мы обнуляем текущий элемент и продолжаем цикл.

Уточняй, если что непонятно.
Ответы: >>2003091 >>2003169
Аноним 2021/04/21 02:16:47  №2003091 12
Ответы: >>2003289
Аноним 2021/04/21 05:26:13  №2003169 13
Ответы: >>2003294
Аноним 2021/04/21 08:36:11  №2003289 14
>>2002857

Да, ты верно описал, формула для расчета offset будет (page - 1) x 100.

>>2002872

Это уже ты выбираешь, сколько страниц выводить. То, что ты описал, вполне подойдет.

>>2003091

Здесь у тебя цикл по сути не используется. Так как у тебя в if/else стоит в обоих ветках break и у цикла всегда выполняется только один шаг. Из-за этого ты проверяешь максимум 3 последние цифры в массиве, а не все.

Если взять, например, запас [5, 5, 5, 5] и комбинацию [1, 5, 5, 5], то программа выдает неправильный результат: https://ideone.com/cflqKZ

Цикл должен работать по-другому:

- увеличиваем текущую цифру, если текущая цифра меньше чем запас, выходим из цикла
- иначе (если текущая цифра >= запаса) записываем вместо нее ноль и продолжаем цикл. На следующем шаге цикл увеличит следующую цифру. Не надо делать это с помощью обращения к элементу [$key-1].

То есть, мы выходим из цикла только если текущая цифра меньше чем запас.

И еще одно улучшение. Чтобы не сортировать массив до и после цикла, можно вместо цикла foreach использовать цикл for с значениями от N - 1 до 0 (где N это количество элементов в массиве).

После этих доработок функция будет готова для использования в программе.



Аноним 2021/04/21 08:45:35  №2003294 15
>>2003144

Функция mysqli_fetch_assoc может вернуть false, null или массив.

При ошибке на стороне БД фукнция вернет false. Надо проверять именно это условие (что вернулось false) и тогда выводить ошибку. А ты выдаешь ошибку даже если функция вернула null, хотя это значит, что данные в таблице не найдены. Это не ошибка базы данных, если например, логин введен неправильно.

>>2003169

Здесь плохо то, что весь код написан внутри одной функции. Лучше разделить код на несколько функций:

- одна функция генерирует следующую комбинацию (и ничем другим не занимается)
- другая считает сумму купюр в комбинации

И наконец, отдельно можно написать код, который в цикле перебирает комбинации:

- сначала берем комбинацию из всех нулей
- далее делаем цикл
- если теущая комбинация дает нужную сумму, то решение найдено, выходим из цикла
- иначе, берем следующую комбинацию (вызывая функцию nextCombination)
- продолжаем цикл

После этой задачи, если ты ее сделаешь, я советую попросить у меня дополнительные задачи на массивы и рекурсию.
Ответы: >>2003601 >>2003746
Аноним 2021/04/21 14:06:26  №2003601 16
>>2003294
Хорошо, при проверке data на false результат тот же
Ответы: >>2003619 >>2003628
Аноним 2021/04/21 14:25:52  №2003619 17
>>2003601
Так, а зачем проверка на false если в data - null, значит проблема в бд или в логине, но я вроде не совсем аутист, в бд есть записи, и логин передается
Аноним 2021/04/21 14:30:49  №2003628 18
>>2003601

Ты проверяешь через == или через ===? Потому что при использовании == (нестрогое сравнение) null будет равен false. Надо использовать ===.

Если функция вернула false, то будет указана причина ошибки. Если функция вернула null, то естественно ошибки нету.
Ответы: >>2003640
Аноним 2021/04/21 14:48:41  №2003640 19
>>2003628
При === возвращает null, данные то все равно не находит
Ответы: >>2004276
Аноним 2021/04/21 16:20:00  №2003746 20
>>2003294
>И наконец, отдельно можно написать код, который в цикле перебирает комбинации:
Не понял, что имеется ввиду.

https://ideone.com/tSOxlD

Вот так пока сделал.
Ответы: >>2004314
Аноним 2021/04/22 09:44:23  №2004276 21
>>2003325

> на деректории стоят права -755,
Ну так если ты не владелец директории, то для тебя права будут 5, то есть r-x, без права на запись (и удаление файлов).

>>2003640

Значит, твой запрос не находит данные. Ты можешь попробовать вместо выполнения SQL-запроса сдампить его и посмотреть, что там получится.

>>2003367

Непонятно, в чем претензия? Шаблоны использовать плохо? Использовать JS код в шаблонах плохо?

Ну в том же реакте, например, в одном файле пишут и JS-код и похожую на HTML разметку. А вместо одного удобного шаблона там куча мелких компонентов - сиди разбирайся.
Аноним 2021/04/22 10:07:43  №2004314 22
>>2003746

Я имел в виду, что мы можем сделать несколько функций, и основной код (либо вне функции, либо в отдельной функции), который их вызывает.

Сейчас у тебя функция nextCombination кроме своей основной задачи (получить следующую комбинацию) делает еще и проверку, подходит эта комбинация или нет. А надо бы сделать, чтобы она только генерировала следующую комбинацию, возвращала ее через return и больше ничего не делала.

Аналогично, вместо функции checkSum, которая и сумму считает, и проверяет, равна ли она требуемой, хорошо бы сделать функцию, которая только считает и возвращает сумму.

То есть, хорошо бы, чтобы каждая функция делала только что-то одно.

А затем написать основной код (либо вне функций, либо в еще одной функции), который и решает задачу, вызывая первые две функции.

-----

Также, после этой задачи советую попробовать решить такие задачи:

1) Дан массив, состоящий из чисел или строк, например: [1, 2, 3]. Сгенерируй и выведи все возможные перестановки значений этого массива. То есть, все возможные способы расставить эти числа или строки без повторов. Для массива выше будет 6 перестановок:

1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

Кстати, перестановки изучает наука комбинаторика.

2) Есть список названий программ. У программ есть зависимости от других программ. Например, чтобы установить программу A, надо сначала установить программы B и C. Список программ дан в массиве такого вида:

$programs = [
// A зависит от B и C
'A' => ['B', 'C'],
// У B нет зависимостей
'B' => [],
// С зависит от D
'C' => ['D'],
'D' => []
]

Также, дано название программы, которую хочет установить пользователь:

$install = 'A';

Выведи, в каком порядке надо устанавливать программы. В данном примере мы должны сначала установить D, тогда мы сможем установить C, потом B, и только потом A.

Дополнительно: сделай обнаружение случаев, когда решить задачу невозможно. Например, если A зависит от B, а B зависит от A, то установить их не получится.

Если захочется погуглить, то это называется задача топологической сортировки.
Ответы: >>2004404 >>2011799
Аноним 2021/04/22 11:10:23  №2004404 23
>>2004314
>А затем написать основной код (либо вне функций, либо в еще одной функции), который и решает задачу, вызывая первые две функции.

Что-то типа этого?
https://ideone.com/tSOxlD

Задачки решу и скину, спасибо.
Ответы: >>2004431
Аноним 2021/04/22 11:35:26  №2004431 24
>>2004404

Да, теперь гораздо лучше.

Вот еще некоторые улучшения, которые можно сделать:

> \tfor($N; $N>=0; $N--){
Здесь стоит либо написать в первом выражении for ($N = count....), либо ничего не писать: for ( ; $N >= 0...). Просто писать $N не имеет никакого смысла.

Также, переменные принято писать с маленькой буквы, потому $n, а не $N.

> \t\t}
>\t\telse{
Правильно писать в одну строку как } else {

> $result = [];
> \tarray_push($result, $sum, $str);
>\treturn $result;
это можно записать короче как return [$x, $y].

У тебя функция checkSum делает две вещи: считает сумму купюр и генерирует строчку для вывода. Но строчка для вывода нам нужна только, если мы нашли правильную комбинацию, в остальных случаях ее генерировать незачем. Можно сделать вместо checkSum 2 отдельных функции. И вызывать функцию генерации строки только когда мы нашли правильную комбинацию.

У тебя в Main используется рекурсия (вызов самой себя). Ее можно заменить на цикл for или while:

Пока (мы не дошли до конца) {
проверить текущую комбинацию;
взять следующую комбинацию;
}

Так будет чуть нагляднее.
Аноним 2021/04/22 12:02:48  №2004452 25
>>2004276
>Шаблоны использовать плохо
Да

>Использовать JS код в шаблонах плохо
Пиздец как плохо

>там куча мелких компонентов
Компонент это атомарная единица, известно как он себя поведет, с темплейтами идет постоянный выеб мозга

>Ну в том же реакте, например, в одном файле пишут и JS-код и похожую на HTML разметку
Там своя хуйня, ничего не скажу за реакт, я с ангуляром работал (в реакте особый язык JSX вроде или как-то так)
Аноним 2021/04/22 12:12:24  №2004466 26
>>2004276
>А вместо одного удобного шаблона
Сваленная в кучу верстка, стили, жс на несколько тысяч строк - удобный шаблон?
В таком шаблоне невозможно понять, где заканчивается один компонент и начинается другой.
Можно с тем же успехом код не разбивать по файлам
Аноним 2021/04/22 13:17:40  №2004547 27
>>2004276
С находом данных разобрался, как у меня обычно бывает это была синтаксическая ошибка
Аноним 2021/04/22 13:38:24  №2004578 28
>>2004276
>Использовать JS код в шаблонах плохо?
>Ну в том же реакте, например, в одном файле пишут и JS-код и похожую на HTML разметку. А вместо одного удобного шаблона там куча мелких компонентов - сиди разбирайся.
Ну ты ебанутый...
Аноним 2021/04/28 08:17:14  №2011186 29
>>2004276
>Как будешь использовать транспилятор при добавлении жс-кода в шаблоны?
>Транспи... что?
>Ясно. Мы вам перезвоним
Аноним 2021/04/28 15:44:30  №2011799 30
>>2004314
>1) Дан массив, состоящий из чисел или строк, например: [1, 2, 3]. Сгенерируй и выведи все возможные перестановки значений этого массива. То есть, все возможные способы расставить эти числа или строки без повторов. Для массива выше будет 6 перестановок:

Че-то тяжко, осилил (если вообще осилил) только на 3 элемента:

https://ideone.com/11ZXON

Это если не гуглить и не смотреть чужие алгоритмы.
Ответы: >>2012720 >>2012721
Аноним 2021/04/29 11:13:45  №2012720 31
>>2011799

У этой задачи есть еще второй, более сложный вариант:

---

Есть массив из N разных чисел (например: [1, 2, 3, 4]), из которых можно генерировать перестановки. Мы можем сравнить, какая из перестановок больше или меньше, таким образом: сравниваем первые цифры, если они равны, сравниваем следующие и так далее, пока не найдем отличающиеся (это называется лексикографический порядок - порядок, который используется в словарях). Например, 3124 < 3142, так как первые 2 цифры у них совпадают, а третья отличается.

Допустим, мы сгенерировали все возможные перестановки и записали их в список по возрастанию.

Вам дается определенная перестановка, найдите следующую за ней, не строя этот список. Например, вам дана перестановка 1342, функция должна вернуть перестановку 1423 (так как 1423 > 1342 и между ними нет других перестановок).

---

Соответственно, есть два способа решения: простое, которое только генерирует список перестановок, и сложное, которое по перестановке находит следующую за ней (используя его, мы можем сгенерировать полный список). Начнем с простого.

Простое решение можно написать, используя рекурсию (когда функция вызывает саму себя). Пусть у нас есть функция getCombinations. На вход она получает массив элементов, на выходе возвращает массив всех возможных перестановок из этих элементов.

Если эта функция получила на вход один элемент [x], то она может сгенерировать и вернуть единственную перестановку: [х]

Если же эта функция получила на вход несколько элементов: [x, y, z], то происходит следующее:

- берем за основу какой-то элемент, например x, и "вынимаем" его из массива, остается [y, z]
- вызываем функцию getCombinations с этим массивом и получаем все возможные перестановки (например: yz и zy)
- приписываем в их начало "вынутый" элемент x, получаем xyz, xzy.

Мы выполняем эти действия для каждого элемента в массиве. То есть, сначала получаем все перестановки, начинающиеся с x, потом с y, потом c z. Так мы получим все возможные перестановки.

То есть наша функция выбирает какой-то один элемент из массива, и вызывает сама себя, но с массивом меньшего размера. Мы сводим задачу "построить перестановки из 3 элементов" к задаче "построить перестановки из 2 элементов" и далее к задаче "построить перестановки из 1 элемента".

Если все понятно, попробуй написать код, если нет, то уточняй.

Далее я опишу решение к сложному варианту задачи.
Ответы: >>2015634
Аноним 2021/04/29 11:15:13  №2012721 32
>>2011799

Теперь мы можем перейти к более сложной задаче: как, имея перестановку, получить следующую за ней в словарном порядке?

Чтобы это понять, мне пришлось выписать несколько примеров перестановок и внимательно их изучить. Рассмотрим пары соседних перестановок, я запишу их вертикально для удобства сравнения:

12345
12354

12354
12435

13542
14235

15243
15324

25431
31245

Если сложно рассматривать примеры из 5 цифр, ты можешь выписать в список по возрастанию все перестановки из 4 цифр - их немного.

Что общего мы видим в этих примерах? Во всех (кроме последнего примера) цифры можно разделить на 2 части: левую часть, которая не меняется, и правая, которая меняется:

123|45
123|54

15|243
15|324

В последнем примере мы поставим черту перед числом, так как там поменялись все цифры:

|25431
|31245

Попробуй подумать над такими вопросами:

- по какому принципу определяется, где поставить черту? Например, где будет черта в комбинации 31542? (подсказка: попробуй сравнивать цифры, идя справа налево)
- после того, как мы поставили черту, по какому принципу меняется цифра справа от черты?
- по какому принципу ставятся цифры справа от черты, кроме первой?

Это наверно сложно, но ты попробуй подумать, а если что, попроси подсказку.

-----

Кстати, по задаче с банкоматом я сделал отдельный разбор, можешь почитать, если любопытно: https://github.com/codedokode/pasta/blob/master/algorithm/atm.md
Аноним 2021/05/01 17:43:11  №2015634 33
bjiidbfeibz (1).jpeg (94, 600x556)
556x600
>>2012720

Как это вообще заработало? У меня знатно протек чердак от этой задачи. Править потом буду, пока просто скидываю что сделал в пол третьего ночи.

https://ideone.com/SnepM5

Чувствую себя пикрелейтед, ничего не гуглил. На "сложную" задачу теперь страшно смотреть.

Мимо все тот же тупой лягушенок
Ответы: >>2015743
Аноним 2021/05/01 18:41:50  №2015743 34
>>2015620

Чтобы помечать место, где строка заканчивается:

$a = <<<END
тут текст
END; // <-- признак конца текста

То есть, текст заключен между END и END.

>>2015634

Неплохо, но тут многое стоит доработать.

Да, программа работает для массива из 4, 3 или 2 элементов. Но она не работает для массива из 5 элементов: она выдает лишь 40, а не 120 комбинаций.

Это из-за того, что ты не используешь рекурсию. Ты можешь в Main() вызывать не getCombinations, а саму же Main(). То есть, тебе пришел массив из 4 элементов, ты вынимаешь один элемент и вызываешь Main() уже с массивом из трех элементов. Только надо чуть доработать функцию Main(). А функция getCombinations тогда будет не нужна вообще.

И еще, я не очень понял принцип работы getCombinations, а именно это место:

> \t\tif($iterations <= $halfIterations){
>\t\t\tkrsort($combination);
>\t\t}

Ты можешь объяснить, почему мы сортируем половину перестановок, а другую половину - не сортируем?

Вот тебе еще идеи по улучшению:

Вывод лучше делать через echo implode(), через пробел, в формате 1 2 3 4. Так читать будет легче.

Ты добавляешь $cutElement в конец массива, и из-за этого у тебя сначала идут все комбинации с 1 на конце, потом с 2 на конце и так далее. Но лучше бы добавлять $cutElement в начало массива.

Цикл foreach внутри getCombinations, как я понял, сдвигает массив (превращая [x, y, z] в [y, z, x]). Этот сдвиг можно было бы сделать через функции array_slice + array_unshift, получилось бы короче и понятнее. Или я что-то не учел?
Ответы: >>2021705
Аноним 2021/05/06 12:42:04  №2021705 35
>>2015743
>Ты можешь объяснить, почему мы сортируем половину перестановок, а другую половину - не сортируем?

Комбинации будут повторяться, если не сортировать.

>Это из-за того, что ты не используешь рекурсию. Ты можешь в Main() вызывать не getCombinations, а саму же Main(). То есть, тебе пришел массив из 4 элементов, ты вынимаешь один элемент и вызываешь Main() уже с массивом из трех элементов. Только надо чуть доработать функцию Main(). А функция getCombinations тогда будет не нужна вообще.

Не могу понять принцип работы, запутался окончательно с этим. Мой алгоритм со сдвигом вообще будет работать с более чем тремя элементами? Ведь при рекурсии он просто начнет повторять уже имеющиеся комбинации, или нет?

https://ideone.com/SnepM5

Я исправил вывод и добавление вырезанного элемента, но с остальным не понимаю что делать.

я совсем тупой что подобные задачи неделями не могу сам решить?
Ответы: >>2021800
Аноним 2021/05/06 14:17:21  №2021800 36
>>2021705

Я думаю, сложности из-за того, что я тебе дал непростую задачу. Рекурсию (когда функция вызывает сама себя) вообще довольно трудно представить в голове. Но некоторые задачи с ней решаются гораздо проще, чем без нее, потому желательно уметь ей пользоваться.

Тебе надо решать больше задач на алгоритмы, и тогда ты сможешь привыкнуть и к работе с массивами, и к рекурсии.

> Мой алгоритм со сдвигом вообще будет работать с более чем тремя элементами?

Не будет. Если у нас 3 элемента [x, y, z], то сдвигами мы получаем 3 комбинации: xyz, yzx, zxy. Затем за счет сортировки мы получаем из них еще 3 комбинации, всего 6. Тут все верно. Но если у нас 4 элемента, то сдвигами мы получаем 4 комбинации, с учетом сортировки получается всего 8 комбинаций. А должно быть 24 комбинации для 4 элементов. Поэтому твоя функция getCombinations работает корректно только с 3 или менее элементами.

Получение комбинаций через сдвиг не работает, если у нас больше 3 элементов.

> Ведь при рекурсии он просто начнет повторять уже имеющиеся комбинации, или нет?

Если использовать рекурсивный алгоритм (не на основе сдвига), то повторов быть не должно. Давай рассмотрим, как работает рекурсивный алгоритм при разном количестве элементов на входе. Вот общий принцип, по которому генерируются перестановки:

Допустим, нам дано 4 элемента [x, y, z, w]. На первое место в перестановке мы можем поставить любой из 4 элементов. Допустим, это x. Далее, на второе место мы можем поставить любой из 3 оставшихся элементов. Допустим, это y. На третье место мы можем поставить один из двух оставшихся элементов: z или w. Пусть это будет z. И на последнее место мы ставим тот элемент, который остался: w. Получилась перестановка xyzw. Выбирая другие элементы, мы получим другие перестановки.

А вот сам алгоритм, работающий по этому принципу:

Функция getCombinations(list):
.... пусть дан массив элементов list
.... если в list один элемент, то вернем единственную комбинацию из этого элемента
.... создаем пустой список комбинаций result
.... берем по очереди элементы list, выбранный элемент помещаем в переменную first:
........ вызываем getCombinations(), передавая ей список list с вырезанным элементом first. Эта функция вернет нам список возможных комбинаций.
........ к каждой из полученных комбинаций в начало приписываем first и добавляем в result
.... конец цикла
.... возвращаем result

Это весь алгоритм. Эта функция может сгенерировать все перестановки из любого числа символов.

Теперь рассмотрим, как будет работать этот алгоритм, если у нас дано 4 элемента: x, y, z, w

- функция вынет из массива x и вызовет себя, чтобы получить все комбинации из элементов y, z, w (их будет 6 штук: yzw, ywz, zyw, zwy, wyz, wzy). К ним в начало она припишет x.
- затем функция вынет из массива y и вызовет себя со списком x, z, w (еще 6 штук)
- затем вынет z и вызовет себя со списком x, y, w
- затем вынет w и вызовет себя со списком x, y, z

Каждый раз мы передаем себе разные наборы букв и потому получаем разные комбинации. И также, каждый раз мы приписываем в начало комбинаций разную букву: первый раз x, второй раз y, в третий z, в четвертый w. Таким образом, все 24 комбинации будут разные.

Попробуй написать эту функцию в виде кода и можешь убедиться, что она будет работать корректно.
Ответы: >>2023760
Аноним 2021/05/08 06:35:32  №2023760 37
>>2021800

>Функция getCombinations(list):
>.... пусть дан массив элементов list
>.... если в list один элемент, то вернем единственную >комбинацию из этого элемента
>.... создаем пустой список комбинаций result
>.... берем по очереди элементы list, выбранный элемент >помещаем в переменную first:
>........ вызываем getCombinations(), передавая ей список list с >вырезанным элементом first. Эта функция вернет нам список >возможных комбинаций.
>........ к каждой из полученных комбинаций в начало >приписываем first и добавляем в result
>.... конец цикла
>.... возвращаем result

Я это понял как:

https://ideone.com/h9J4W5

Ничего не работает. Я посмотрел простой пример работы рекурсии в нахождении факториала, там более-менее понятно, а что происходит здесь, и почему мы вызываем функцию внутри цикла, которая затем возвращает все имеющиеся комбинации (каким образом?) - мне непонятно.
Функция неполная и мне нужно ее как-то переделать или я не могу понять ее принцип?
Ответы: >>2024131 >>2024149
Аноним 2021/05/08 12:08:16  №2024131 38
>>2023760

У тебя есть ошибки в реализации функции.

Во-первых, проблема тут:

>\tif(count($list) == 1){
>\t\treturn current($list);
>\t}

Мы решили, что функция возвращает список комбинаций. Одна комбинация - это массив: [1, 2, 3], список комбинаций - это массив массивов [[1, 2, 3], [3, 2, 1]], даже если там всего один элемент. Надо возвращать тут массив массивов.

> \t\tforeach($combination as $el){
>\t\t\tarray_unshift($el, $first);
Здесь ты добавляешь элемент в $el. Но $el это не комбинация из $combination, а копия этой комбинации. Ты меняешь копию в $el, а оригинал в $combination остается неизменным.

> $result[] = $combination;
Здесь тоже ошибка. $result это список комбинаций: [k1, k2, k3] (где k1..3 - это одна комбинация в виде массива). $combination это тоже список комбинаций. Надо либо объединять эти списки, либо добавлять в result кобминации по одной, а не все сразу. Ты же вкладываешь список внутрь списка и из-за этого у тебя получился массив сложной формы.

Также, некоторые переменные названы неудачно, и это затрудняет чтение программы:

- $list лучше назвать $elements (да, я в алгоритме написал list, но это неудачное название)
- $value тогда станет $element
- $combination это не одна комбинация, а список потому надо добавить s в конце
- а вот $el переименовать в $combination

Если все это исправить, программа должна заработать. Пиши, если еще есть какие-то вопросы.

Ответы: >>2025372
Аноним 2021/05/08 12:18:56  №2024149 39
>>2023760

> почему мы вызываем функцию внутри цикла

Мы используем цикл, чтобы по очереди вынуть каждый элемент из списка. Если нам дан список x, y, z, w, то мы сначала вынимаем x, потом y, и так далее. Потому мы используем цикл, чтобы обойти все элементы по очереди.

Мы вызываем функцию (саму себя), чтобы получить список всех комбинаций из меньшего числа элементов. Если нам дали 4 элемента, то мы вынимаем один и вызываем функцию с 3 элементами. Если нам дали, например, 2 элемента, то мы вынимаем один и вызвываем функцию с одним элементом.

> которая затем возвращает все имеющиеся комбинации (каким образом?)

Попробуй рассмотреть, как функция работает, если ей дать 1 элемент. Затем, как она работает с 2 элементами. Затем с тремя. И так далее.

Если нам дали один элемент, то мы возвращаем единственную комбинацию из него.

Далее, допустим, у нас 2 элемента x и y. Функция работает так:

- вынимаем элемент x, вызываем саму себя с элементом y. Добавляем x в начало, получаем комбинацию xy
- вынимаем элемент y, вызываем саму себя с элементом x. Получаем комбинацию yx.

Для 2 элементов, как видно, все комбинации найдены. Рассмотрим ситуацию с 3 элементами x, y, z.

- вынимаем элемент x, остаются y, z. Вызываем себя, и получаем 2 комбинации из элементов y, z: yz и zy. Приписываем к ним в начало x, получаем xyz и xzy.
- вынимаем элемент y и делаем те же шаги. Получим комбинации yxz и yzx.
- вынимаем элемент z и получаем комбинации zxy и zyx

Для трех элементов функция смогла найти все 6 комбинаций.

Дальше можешь рассмотреть, как функция будет работать с 4 элементами.
Аноним 2021/05/09 09:07:24  №2025372 40
Ответы: >>2025967
Аноним 2021/05/09 16:25:56  №2025967 41
>>2025372

Ты удаляешь элемент из $elements с помощью unset, но не добавляешь его обратно.
Ответы: >>2026028
Аноним 2021/05/09 17:00:00  №2026028 42
>>2025967
Заработало, спасибо. Теперь буду пытаться вникнуть как она работает (вопросов пока нет).