Python вызов: зомби - PullRequest
       7

Python вызов: зомби

2 голосов
/ 03 февраля 2020

Я пытаюсь решить следующую задачу, но безрезультатно: зомби начинают с дальномеров и движутся со скоростью 0,5 метра в секунду. Каждую секунду вы сначала стреляете в одного зомба ie, а затем оставшиеся зомби шатаются вперед еще на 0,5 метра.

Если каким-либо зомби удастся добраться до 0 метров, вас съедят. Если у вас закончатся боеприпасы, прежде чем стрелять во всех зомби, вас тоже съедят. Для простоты мы можем игнорировать любое время, потраченное на перезагрузку.

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

Если Вы стреляете во всех зомби, возвращаете «Вы стреляли во всех X зомби». Если вас съели до того, как убить всех зомби, и до того, как закончились боеприпасы, верните «Вы стреляли в X зомби до того, как их съели: поражены». Если у вас закончились боеприпасы до стрельбы по всем зомби, верните «Вы стреляли в X зомби до того, как их съели: кончились боеприпасы».

(Если у вас кончились патроны одновременно с достижением оставшихся зомби вы возвращаете «Вы стреляли в X зомби перед тем, как их съели: ошеломлены».)

Пока мой код:

def zombie_shootout(zombies, distance, ammo):
    if ammo >= zombies:
        ammo -= 1
        zombies -= 1
        distance -= 0.5
    elif ammo < zombies:
        print("You shot ",zombies,"zombies before being eaten: ran out of ammo.")
    elif distance == 0:
        print("You shot ",zombies,"zombies before being eaten: overwhelmed.")
    else:
        print("You shot all ", zombies,"zombies.")

Я знаю, что есть решения для тех, кто не может решить это загадка, но они, скорее всего, гораздо более лаконичны и изящны, и я хотел бы знать, как (если это вообще возможно) go сделать это по-своему (много ifs и elifs и, возможно, добавить некоторое время где-то).

Ответы [ 3 ]

2 голосов
/ 03 февраля 2020

Хотя ответ @CDJB действительно хорош, я хотел бы указать на другой подход, который также работает, но немного быстрее (в вычислительном отношении). Причина, по которой это может быть важно, заключается в том, что если весь мир потерпит неудачу, вам придется иметь дело с ~ 7.000.000.000 зомби, поэтому некоторое время l oop займет очень много времени.

Мы знаем, что зомби начинаются на расстоянии x м, и мы можем стрелять 1 зомба ie на каждые 0,5 м пройденного. Это означает, что мы можем стрелять:

 zombies_shot_distance = int(distance * 2)

Мы также знаем, что не можем стрелять больше зомби, чем у нас есть патроны, поэтому:

 zombies_shot_ammo = ammo

Максимальное количество выстрелов зомби самое низкое из два:

 zombies_shot_max = min(zombies_shot_distance, zombies_shot_ammo)

Если максимальное количество выстрелов зомби меньше, чем количество зомби, мы знаем, что не сможем застрелить всех зомби:

if zombies > zombies_shot_max:
    print("You shot", zombies_shot_max, "zombies")
    if zombies_shot_ammo <= zombies_shot_distance:
         print("because you ran out of ammo")
    else:
         print("because you were overwhelmed")
else:
    print("You shot all the zombies")
2 голосов
/ 03 февраля 2020

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

def zombie_rec(zombies, distance, ammo, shot):
    if zombies <= 0:
        return f"You shot all {shot} zombies."
    elif ammo <= 0:
        return f"You shot {shot} zombies before being eaten: ran out of ammo."
    elif distance <= 0:
        return f"You shot {shot} zombies before being eaten: overwhelmed."

    else:
        return zombie_rec(zombies - 1, distance - 0.5, ammo - 1, shot + 1)

def zombie(zombies, distance, ammo):
    print(zombie_rec(zombies, distance, ammo, 0))

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

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

  1. Все зомби мертвы, и мы выигрываем.
  2. Дистанция равна нулю, и мы съедены (сейчас).
  3. Боеприпасы ноль и мы съедены (в конце концов).

Обратите внимание, что мы должны проверить их в этом порядке, так как zombies == 0 означает, что мы живем, даже если два других также равны 0.

Если ни одно из следующих условий не выполняется, то мы должны go сделать еще один ход. Это можно сделать с помощью рекурсивного вызова, отметив, что

  1. zombies и ammo все уменьшилось на 1 и distance на 0,5. (Когда мы стреляли в зомба ie, а остальные продвинулись).
  2. Мы увеличиваем shot на 1, чтобы отследить число выстрелов в конце этого раунда.

Подобно while циклам, мы должны дважды проверить, что мы заверены и заверены в бесконечности l oop. В этом случае мы уверены, что либо zombies, distance, либо ammo достигнут нуля, поскольку все они уменьшаются на 1 каждый шаг.

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

Если вам интересно узнать больше о рекурсии, Я настоятельно рекомендую Маленький интриган

2 голосов
/ 03 февраля 2020

Давайте go через ваш код: вы сказали в комментариях, что знаете, что вам нужно где-то while l oop, так что давайте подумаем, какое условие мы должны наложить на этот l oop. Мы хотим продолжать стрелять до тех пор, пока у нас не кончатся патроны, нас не съедят зомби или у нас не кончатся зомби. Мы можем сделать это, используя all(), чтобы проверить, что все переменные больше 0:

while all(x > 0 for x in (distance, ammo, zombies)):

Это эквивалентно:

while distance>0 and ammo>0 and zombies>0:

Пока это условие True, мы хотим применить логику c в вашем вопросе, которая уже была в вашем заявлении if. Вы также хотите напечатать количество убитых зомби, поэтому давайте добавим переменную zombies_shot, установим ее в 0 в начале функции и будем увеличивать ее каждый раз, когда мы запускаем наш while l * 1029. *. Теперь у нас есть:

def zombie_shootout(zombies, distance, ammo):
    zombies_shot = 0
    while all(x>0 for x in (distance, ammo, zombies)):
        ammo -= 1
        zombies_shot += 1
        zombies -= 1
        distance -= 0.5

Итак, теперь нам нужно проверить условия после того, как мы вышли из while l oop. У вас это тоже почти получилось, но давайте также проверим, остались ли еще зомби, в противном случае, если мы застрелим последнего зомба ie, например, перед тем, как он достигнет нас, ваша функция все равно скажет, что нас съели. Мы также можем использовать новую переменную zombies_shot.

if ammo <= 0 and zombies > 0:
    print("You shot",zombies_shot,"zombies before being eaten: ran out of ammo.")
elif distance <= 0 and zombies > 0:
    print("You shot",zombies_shot,"zombies before being eaten: overwhelmed.")
else:
    print("You shot all", zombies_shot,"zombies.")

Мы могли бы также добавить return операторы вместо print операторов, но это ваше дело. Наша полная функция теперь:

def zombie_shootout(zombies, distance, ammo):
    zombies_shot = 0
    while all(x>0 for x in (distance, ammo, zombies)):
        ammo -= 1
        zombies_shot += 1
        zombies -= 1
        distance -= 0.5
    if ammo <= 0 and zombies > 0:
        print("You shot",zombies_shot,"zombies before being eaten: ran out of ammo.")
    elif distance <= 0 and zombies > 0:
        print("You shot",zombies_shot,"zombies before being eaten: overwhelmed.")
    else:
        print("You shot all", zombies_shot,"zombies.")
...