Снова Хэллоуин!

10

описание проблемы

Мы все любим твикс (потому что это самая лучшая конфета), но это первый детский праздник Хэллоуина - нам нужно захватить хотя бы одну конфету каждого типа для них. Каждый Хэллоуин все жители Numberline avenue рассылают электронные письма, в которых говорится, какие конфеты они будут разыгрывать в этом году.

Ой! И мы живем в одномерном мире.

Будучи исключительно ленивыми в некоторых отношениях, а не в других, мы составили карту домов, на которых показано их расположение вдоль улицы. Мы также отметили типы конфет, которые они имеют. Вот карта, которую мы сделали на этот год:

 [(-2, {"Kisses", "KitKats"}),
 (1, {"KitKats", "Peanut Butter Cups"}),
 (6, {"Kisses", "Twix"}),
 (9, {"Skittles"}),
 (10, {"Twix"})]

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

Примеры

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

 [(-2, {"Kisses", "KitKats"}),
 (1, {"KitKats", "Peanut Butter Cups"}),
 (6, {"Kisses", "Twix"}),
 (9, {"Skittles"}),
 (10, {"Twix"})]

Вывод:

[1, 2, 3]

Еще одна карта и решение ...

Входные данные:

[(-3, {"KitKats", "Twix"}),
(-1, {"Hundred Grands"}),
(3, {"Kisses"}),
(12, {"Hundred Grands", "Twix", "KitKats"})]

Выход :

[0, 1, 2]

Мы могли бы начать в доме с координатами 9, собирая конфеты в дома 6 и 1. Это заполняет квоту на конфеты, пройдя 8 единиц, но является ли это кратчайшим решением?

правила

Записи должны принимать аналогично структурированному единственному аргументу к примеру и выводить индексы домов для посещения в кратчайшем решении.

Применяются типичные правила игры в гольф: выигрывает самое короткое правильное решение в байтах!

PS Это был вопрос для интервью, данный мне одной из крупнейших мировых технологических компаний. Если вам не нравится гольф, попробуйте найти временное решение O (k * n), где k - количество конфет, а n - количество домов.

редактировать

Как отметил Джонатон Аллан, существует некоторая путаница в отношении того, что в данном случае означают «индексы». Мы хотим вывести позиции домов в списке аргументов, а не их координаты на дорожке.

Qfwfq
источник
6
Это требует проработанного примера и некоторых тестовых случаев.
Лохматый
2
Можем ли мы принять два аргумента; список номеров домов и соответствующий список типов конфет?
Адам
1
@KevinCruijssen Ни то, ни другое: выведите индексы домов для посещения в кратчайшем решении
Адам
2
Я предположил, что «индексы» и «позиции» были синонимами (то есть, что адреса на Numberline Avenue были бы тем, что мы должны вернуть), это неправильно?
Джонатан Аллан
1
@KevinCruijssen Отличные вопросы! Числа гарантированно будут в порядке на входе. И я позволю предположить, что строки не содержат цифр, поскольку все конфеты, которые я знаю с цифрами, обозначают их (Сто градов и три мушкетера). :)
Qfwfq

Ответы:

3

Желе , 16 байт

ŒPṪ€ẎQLƲÐṀẎISƊÞḢ

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

Попробуйте онлайн!

Если мы хотим найти все такие кратчайшие пути, заменим конечные байты ÞḢна ÐṂ; это также 16 байтов.

Как?

ŒPṪ€ẎQLƲÐṀẎISƊÞḢ - Link: list of [index, candies]
ŒP               - power-set
        ÐṀ       - keep those for which this is maximal:
       Ʋ         -   last four links as a monad:
  Ṫ€             -     tail €ach -- this removes the candies lists from the current list
                 -                  and yields them for use now
    Ẏ            -     tighten (to a flat list of candies offered by these hoses)
     Q           -     de-duplicate (get the distinct candies offered)
      L          -     length (how many distinct candies are on offer)
              Þ  - sort (now just the indexes of remaining sets due to Ṫ) by:
             Ɗ   -   last three links as a monad:
          Ẏ      -     tighten (to a flat list of indexes since Ṫ leaves a list behind)
           I     -     incremental differences (distances between houses)
            S    -     sum
               Ḣ - head (get the first)
Джонатан Аллан
источник
1
Ницца. Для вашего объяснения, я думаю, вы имеете в виду максимальный для второго быстрого.
Ник Кеннеди
Да, я это сделал.
Джонатан Аллан
2

05AB1E , 22 байта

æʒ€θ˜I€θ˜åP}€€нD€¥OWQÏ

Предполагается, что числа в списке ввода отсортированы по возрастанию.
Если найдено более одного решения, оно выведет их все.

Попробуйте онлайн.

Объяснение:

æ            # Get the powerset (all possible combinations) of the (implicit) input-list
 ʒ           # Filter this list of combinations by:
  €θ         #  Get the last items of each (the list of strings)
    ˜        #  Flatten the list
  I          #  Get the input-list again
   €θ˜       #  Get the last items of each (the list of strings) flattened as well
      å      #  Check for each if it is in the list of strings of this combination
       P     #  Check if all are present
 }           # Close the filter (we now have all combinations, containing all unique strings)
  €€н        # Only leave the first items of each item in the combination (the integers)
     D       # Duplicate this list
      €¥     # Get the deltas (forward differences) of each
        O    # Sum these deltas
         W   # Get the lowest sum (without popping the list)
          Q  # Check for each if it's equal to this minimum
           Ï # And only leave the list of integers at the truthy indices
             # (which are output implicitly as result)
Кевин Круйссен
источник
0

Haskell , 343 372 байта

Благодаря @ ASCII-only для улучшений, есть также 271-байтовый вариант, который он предложил в комментариях :)

import Data.List
import Data.Function
f s=subsequences(map(\a@(x,y)->(x,y,[(a`elemIndices`s)!!0]))s)
g f s=if f*s<=0 then f+abs f+abs s else f+abs(f-s)
h=foldl(\(a,b,c)(d,e,f)->(g a d,nub(b++e),c++f))(0,[],[])
i s=map h(filter(not.null)s)
l m=filter(\(_,x,_)->length x==(maximum$map(\(_,x,_)->length x)m))m
m=minimumBy(compare`on`(\(p,_,_)->p))
n s=(\(_,_,l)->l)$m$l$i$f s

Попробуйте онлайн!


Ungolfed

import Data.List
import Data.Function

allPaths :: [(Integer, [String])] -> [[(Integer, [String], [Int])]]
allPaths xs = subsequences(map (\a@(x,y) -> (x,y,[(a`elemIndices`s) !! 0])) s)

pathLength :: Integer -> Integer -> Integer
pathLength f s = if f*s <= 0 then f + abs f + abs s else f + abs(f - s)

traversePath :: [(Integer, [String], [Int])] -> (Integer, [String], [Int])
traversePath = foldl (\(n1, a1, c1) (n2, a2, c2) -> (pathLength n1 n2, nub (a1 ++ a2), c1 ++ c2)) (0, [], [])

allTraversedPaths :: [[(Integer, [String], [Int])]] -> [(Integer, [String], [Int])]
allTraversedPaths xs = map traversePath (filter (not . null) xs)

getCompletePaths :: [(Integer, [String], [Int])] -> [(Integer, [String], [Int])]
getCompletePaths m = filter (\(_,x,_) -> length x == ( maximum $ map (\(_,x,_) -> length x) m)) m

getFastestPath :: [(Integer, [String], [Int])] -> (Integer, [String], [Int])
getFastestPath = minimumBy (compare `on` (\(p, _, _) -> p))

getPath :: [(Integer, [String])] -> (Integer, [String], [Int])
getPath xs = (\(_,_,l) -> l) getFastestPath $ getCompletePaths $ allTraversedPaths $ allPaths xs

Первая попытка

ошибки
источник
вы должны вернуть только третий элемент этого кортежа, и после импорта у вас появляется посторонний
символ
315? (все еще должен возвращать только третий элемент)
ASCII-only
а на самом деле ... это даже не работа на втором TestCase
ASCII-только
так что да, вы не можете жестко закодировать длину
только ASCII
358
только для ASCII,
0

O (k * n) временное решение, с O (k * n) пространством

xii0i<nxicii

i1j1i0<i1i0j0i0j0

Таким образом, наш алгоритм:

// A[k] is the number of each candy we get from the first k houses
A := array of n bags
A[0] := {}
for k := 0 to n - 1
  A[k] := A[k - 1] + c[k - 1]
end
best_distance := ∞
best_i := -1
best_j := -1
// Find the range [i, j] such that we get all candy types
j := n
for i := n - 1 to 0
  while j > i and (A[j - 1] - A[i]) has all candy types
    j := j - 1
  end
  if (A[j] - A[i]) does not have all candy types then continue end
  distance = x[j - 1] - x[i]
  if distance < best_distance then
    best_distance = distance
    best_i = i
    best_j = j
  end
end
return best_i ..^ best_j

AO(k)O(nk)nnnO(n)O(nk)O(k)O(nk)

bb94
источник