Google Foobar: Как найти граничные случаи и идентифицировать тестовые случаи. питон
Проблема
Совершенство впрыска топлива
Коммандер Лямбда попросил вашей помощи усовершенствовать систему автоматического впрыска топлива с квантовой антивеществой для своего устройства LAMBCHOP конца света. Для вас это отличный шанс поближе познакомиться с LAMBCHOP - и, может быть, немного саботировать, пока вы там - так что вы с радостью взялись за работу.
Топливо Quantum Antimatter поставляется в виде небольших гранул, что удобно, так как каждая движущаяся часть LAMBCHOP должна подавать топливо по одной грануле за раз. Однако миньоны сбрасывают пеллеты навалом в забор топлива. Вам необходимо найти наиболее эффективный способ сортировки и переноса гранул в одну таблетку за раз.
Механизмы контроля топлива имеют три операции:
Добавьте одну топливную таблетку. Удалите одну топливную таблетку. Разделите всю группу топливных таблеток на 2 (из-за деструктивной энергии, выделяющейся, когда гранула с квантовой антивеществом разрезается пополам, меры безопасности позволят этому случиться только при четном количестве шарики) Напишите функцию с именем answer(n), которая принимает в качестве строки положительное целое число и возвращает минимальное количество операций, необходимых для преобразования числа шариков в 1. Панель управления впускным отверстием для топлива может отображать только число длиной до 309 цифр. так что не будет больше гранул, чем вы можете выразить в таком количестве цифр.
Например: answer(4) возвращает 2: 4 -> 2 -> 1 ответ (15) возвращает 5: 15 -> 16 -> 8 -> 4 -> 2 -> 1
Контрольные примеры
Входные данные: (строка) n = "4" Выходные данные: (int) 2
Входные данные: (строка) n = "15" Выходные данные: (int) 5
Вот мое решение:
import math
import decimal
def answer(n):
n = long(n)
if n <= 1 or n >= long('9' * 309):
return 0
# 1. Find closest power of 2
round_threshold_adjust = math.log(3,2)- (1.5)
log_n = math.log(n, 2)
power = log_n - round_threshold_adjust
# Round power down if X.50000. If n is equally between two powers of 2,
# choose the lower power of 2. E.g. For 6, choose, 4 not 8
power2 = long(decimal.Decimal(power).quantize(0, decimal.ROUND_HALF_DOWN))
# 2. Calculate the difference, add to iterations
# 3. Take log 2 of that, add that to iteration
iters = abs(n - 2**power) + power
return(iters)
Мое решение в настоящее время проходит 3 из 10 тестовых случаев. Я полагаю, что другие тестовые случаи - крайние случаи. Можете ли вы дать мне несколько советов о том, как я могу определить, где мой код не работает? (У меня нет доступа к тестам)
Вот некоторые из тестовых случаев, которые я пробовал:
assert answer(15) == 5
assert answer(4) == 2
assert answer(3) == 2
assert answer(2) == 1
assert answer(6) == 4
assert answer(7) == 4
assert answer(10) == 5
assert answer(1024) == 10
assert answer(1025) == 11
assert answer(1026) == 12
assert answer(1027) == 13
assert answer(768) == 256 + 9
1 ответ
Вот мое решение:
#!/usr/bin/python
#fuel-injection-perfection
#Program to count the naximum number of operations needed to recursively divide a number by 2. Add or subtract 1 where needed.
#V2 - Initial version was done using recursion but failed for large numbers due to python limitation & performance issues.
cnt=0
def divide(x):
global cnt
while(x>1):
if (x & 1==0):
#Dividing even number by two by shifting binary digits one step to the right.
x=x>>1
else:
a=x+1
b=x-1
#counters ac & bc will be used to count trailing 0s
ac=bc=0
#count trailing 0's for x+1
while(a & 1==0):
a=a>>1
ac+=1
#count trailing 0's for x-1
while(b & 1==0):
b=b>>1
bc+=1
#go with x+1 if it has more trailing 0s in binary format. Exception is number 3 as b10 can be divided in less steps than b100.
#edge case 3 identified by manually testing numbers 1-10.
if (ac>bc and x!=3):
x+=1
else:
x-=1
cnt+=1
def solution(n):
global cnt
n=int(n)
divide(n)
return cnt
Если я правильно понял, что при 768 гранулах вам нужно 256+9 шагов, чтобы преобразовать это в 1 гранулу?
Я могу сделать это в 10 шагов:
- Разделите 768 на 2
- Повторите еще 7 раз -> вы получите 3 гранулы
- Вычесть 1
- Вычесть 1
Я думаю, что ваш первый шаг, сложение / вычитание, пока вы не достигнете степени 2, не является самым быстрым решением.
Я не уверен, как написать лучшее решение, но, возможно, это указывает вам верное направление. Интуитивно понятно, что моим следующим шагом будет просмотр двоичного представления числа и перевод разрешенных операций в это представление. Это может упростить создание правильного алгоритма.
Это ответ Python3. Я создал функцию буксировки, одну с добавлением 1, а другую с вычитанием 1, а затем сравнение, которое дает лучший ответ с наименьшим количеством шагов.
#function for the adding 1 to the odd number
def np(n):
c = 0
while n > 1:
if n%2 == 0:
n = n/2
c += 1
else:
n += 1
c += 1
return c
#function for the subtracting 1 to the odd number
def nn(n):
c = 0
while n > 1:
if n%2 == 0:
n = n/2
c += 1
else:
n -= 1
c += 1
return c
#Solution function
def solution(n):
n = int(n)
if np(n) > nn(n):
return nn(n)
else:
return np(n)
Надеюсь, это сработает, ура.