Подсчет в пирамидах


17

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

Начиная с исходного списка на каждом шаге, мы создаем новый с максимальными значениями каждой пары соседних чисел (например, 5 1 2 6становится 5 2 6). Мы останавливаемся, когда в списке только один номер.

Полная пирамида для 5 1 2 6IS

5 1 2 6
 5 2 6 
  5 6  
   6   

Результирующее количество вхождений есть 3 1 2 4( 5 1 2 6соответственно).

вход

  • Список из одного или нескольких целых чисел без повторений. (например 1 5 1 6, неверно.)

Выход

  • Список целых положительных чисел. iЙ элемент списка является числом вхождений iго входного числа в пирамидах.

Примеры

Вход => Выход

-5 => 1

8 4 => 2 1

5 9 7 => 1 4 1

1 2 3 9 8 6 7 => 1 2 3 16 3 1 2

6 4 2 1 3 5 => 6 4 2 1 3 5

5 2 9 1 6 0 => 2 1 12 1 4 1

120 5 -60 9 12 1 3 0 1200 => 8 2 1 3 16 1 4 1 9

68 61 92 58 19 84 75 71 46 69 25 56 78 10 89 => 2 1 39 2 1 27 6 5 1 6 1 2 14 1 12

Это код-гольф, поэтому выигрывает самый короткий вход.

Бонусная головоломка: вы можете решить проблему O(n*log n)вовремя?


Для отправки функции мне нужно распечатать их в STDOUT или просто вывести их?
Оптимизатор

Ответы:


4

Pyth, 19 17 байт

m/smmeSb.:QhkUQdQ

Проверьте онлайн-демонстрацию или полный комплект тестов (первые 4 байта повторяются в примерах).

Этот немного умнее, чем наивный подход. Каждое число треугольника может быть представлено как максимальное значение связного подмножества Q. В первой строке используются подмножества длины 1, во второй строке треугольника используются подмножества длины 2, ...

объяснение

m/smmeSb.:QhkUQdQ    implicit: Q = input()
   m         UQ         map each k in [0, 1, 2, ..., len(Q)-1] to:
        .:Qhk              all subsets of Q of length (k + 1)
    meSb                   mapped to their maximum
  s                     join these lists together
m               Q    map each d of Q to:
 /             d        its count in the computed list

Чтобы визуализировать это немного. m.:QhdUQи ввод [5, 1, 2, 6]дает мне все возможные подмножества:

[[[5], [1], [2], [6]], [[5, 1], [1, 2], [2, 6]], [[5, 1, 2], [1, 2, 6]], [[5, 1, 2, 6]]]

И mmeSk.:QhdUQдает мне каждый из их максимумов (который точно соответствует строкам в пирамиде):

[[5, 1, 2, 6], [5, 2, 6], [5, 6], [6]]

Pyth, 23 22 байта

|u&aYGmeSd.:G2QQm/sYdQ

Это простой подход «делай то, что тебе говорят».

Проверьте онлайн-демонстрацию или полный комплект тестов (первые 4 байта повторяются в примерах).

объяснение

meSd.:G2сопоставляет каждую пару [(G[0], G[1]), (G[1], G[2]), ...]с максимальным элементом.

Yэто пустой список, поэтому aYGдобавляется Gв Y.

u...QQповторно применяет эти две функции ( len(Q)время), начиная с G = Qи обновляя Gпосле каждого запуска.

m/sYdQсопоставляет каждый элемент входного списка с их количеством в плоском Yсписке.


ваша 17-байтовая версия использует тот же алгоритм, что и мой, я полагаю, что теперь он также наивен: P
Оптимизатор

13

Python, 81

def f(L):
 if L:i=L.index(max(L));L=f(L[:i])+[~i*(i-len(L))]+f(L[i+1:])
 return L

Решение «разделяй и властвуй». Элемент максимума Mпросачивается вниз по всей пирамиде, разбивая его на прямоугольник Mс двумя подпирамидами.

* * * M * *
 * * M M *
  * M M M
   M M M
    M M
     M

Итак, общий результат - это вывод для левого подсписка, за которым следует область прямоугольника, а затем вывод для правого подсписка.

Входная переменная Lиспользуется повторно для сохранения результата, так что пустой список отображается на пустой список.

Конструкции в решении многословны в Python. Может быть, какой-нибудь язык с сопоставлением с образцом может реализовать следующий псевдокод?

def f(L):
 [] -> []
 A+[max(L)]+B -> f(A)+[(len(A)+1)*(len(B)+1)]+f(B)

Я могу сделать один байт короче с сопоставлением с образцом Mathematica, но он даже не превосходит существующее представление Mathematica:f@{}=##&@@{};f@{a___,l_,b___}/;l>a~Max~b:={f@{a},Length@{a,0}Length@{b,0},f@{b}}
Мартин Эндер,

6

CJam, 23 22 байта

Все еще ищу варианты игры в гольф.

{]_,{)W$ew::e>~}%fe=~}

Это функция CJam (вроде). Это ожидает входные числа в стеке и возвращает соответствующие выходные значения в стеке. Пример:

5 1 2 6 {]_,{)W$ew::e>~}%fe=~}~

уходит

3 1 2 4

в стеке.

Уверен, что это не O(n log n)вовремя.

Расширение кода :

]_                     e# Wrap the input numbers on stack in an array and take a copy
  ,{          }%       e# Take length of the copy and run the loop from 0 to length - 1
    )W$                e# Increment the iterating index and copy the parsed input array
       ew              e# Get overlapping slices of iterating index + 1 size
         ::e>          e# Get maximum from each slice
             ~         e# Unwrap so that there can be finally only 1 level array
                fe=    e# For each of the original array, get the occurrence in this
                       e# final array created by the { ... }%
                   ~   e# Unwrap the count array and leave it on stack

Давайте посмотрим, как это работает, на примере 5 1 2 6

Во втором ряду 5 1 2 6становится 5 2 6потому , что 5, 2 and 6это максимум [5 1], [1 2] and [2 6]соответственно. В третьем ряду это делается 5 6потому 5 and 6, что максимально [5 2] and [2 6]соответственно. Это также может быть записано как максимум [5 1 2] and [1 2 6]соответственно. Аналогично для последней строки, 6это максимум [5 1 2 6].

Таким образом, мы в основном создаем срезы правильной длины, начиная от среза длины 1, который в основном является исходными числами, каждый из которых заключен в массив, и, наконец, срезом длины Nдля последней строки, где Nнаходится число входных целых чисел.

Попробуйте это онлайн здесь



3

Python, 81

lambda L:[sum(x==max(L[i:j])for j in range(len(L)+1)for i in range(j))for x in L]

Каждая запись пирамиды является максимумом подсписка наверху его конуса. Итак, мы генерируем все эти подсписки, индексируемые интервалами [i,j]с 0 < i < j <= len(L), и подсчитываем, сколько раз каждый элемент появляется как максимум.

Более короткий способ перечисления подинтервалов, скорее всего, сохранит символы. Одноиндексная параметризация пар [i,j]была бы правдоподобным подходом.


1

Пип , 56 + 1 = 57 байт

Боюсь, я не очень-то конкурирую с CJam вуду. Похоже, мне нужен лучший алгоритм. Запустите с -sфлагом, чтобы получить разделенный пробелами вывод.

l:gr:0*,#gg:0*g+1WrFir:{c:r@[a--a]c@($<l@c)}M1,#r++(gi)g

Ungolfed, с комментариями:

l:g                              l = input from cmdline args
r:0*,#g                          r = current row as a list of indices into l
g:0*g+1                          Repurpose g to store the frequencies
Wr                               Loop until r becomes empty
 Fir:{c:r@[a--a]c@($<l@c)}M1,#r  Redefine r (see below) and loop over each i in it
  ++(gi)                         Increment g[i]
g                                Output g

Переопределение rкаждого времени через работает следующим образом:

{c:r@[a--a]c@($<l@c)}M1,#r
{                   }M1,#r       Map this function to each a from 1 to len(r) - 1:
 c:r@[a--a]                      c is a two-item list containing r[a] and r[a-1]
                l@c              The values of l at the indices contained in c
              $<                 Fold/less-than: true iff l[c[0]] < l[c[1]]
           c@(     )             Return c[0] if the former is greater, c[1] otherwise

1

APL (24)

{+/⍵∘.={⍵≡⍬:⍵⋄⍵,∇2⌈/⍵}⍵}

Это функция, которая принимает список, вот так;

      {+/⍵∘.={⍵≡⍬:⍵⋄⍵,∇2⌈/⍵}⍵}68 61 92 58 19 84 75 71 46 69 25 56 78 10 89
2 1 39 2 1 27 6 5 1 6 1 2 14 1 12

Объяснение:

  • {... }⍵: применить следующую функцию к ⍵:
    • ⍵≡⍬:⍵: если empty пусто, вернуть ⍵
    • 2⌈/⍵: создать следующий список
    • ⍵,∇: return ⍵, а затем результат применения этой функции к следующему списку
  • ⍵∘.=: сравнить каждый элемент в ⍵ с каждым элементом в результате функции
  • +/: сумма строк (представляющих элементы в ⍵)

1

Haskell, 78 байт

l=length
f x=[l[b|b<-concat$take(l x)$iterate(zipWith max=<<tail)x,a==b]|a<-x]

Использование: f [68,61,92,58,19,84,75,71,46,69,25,56,78,10,89]-> [2,1,39,2,1,27,6,5,1,6,1,2,14,1,12].

Как это устроено

zipWith max=<<tail   -- apply 'max' on neighbor elements of a list
iterate (...) x      -- repeatedly apply the above max-thing on the
                     -- input list and build a list of the intermediate
                     -- results
take (l x) ...       -- take the first n elements of the above list
                     -- where n is the length of the input list
concat               -- concatenate into a single list. Now we have
                     -- all elements of the pyramid in a single list.
[ [b|b<-...,a==b] | a<-x]
                     -- for all elements 'a' of the input list make a 
                     -- list of 'b's from the pyramid-list where a==b.
 l                   -- take the length of each of these lists    

1

JavaScript, 109 байт

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

f=s=>{t=[];for(i=-1;s.length>++i;){j=k=i;l=r=1;for(;s[--j]<s[i];l++);for(;s[++k]<s[i];r++);t[i]=l*r}return t}

Я использую следующую формулу здесь:

вхождения i = (количество последовательных чисел меньше i слева + 1) * (количество последовательных чисел меньше i справа + 1)

Таким образом, не нужно фактически генерировать всю пирамиду или ее подмножества. (Именно поэтому я изначально думал, что он будет работать в O (n), но, к счастью, нам все еще нужны внутренние циклы.)


1

МАТЛАБ: (266 б)

  • исправление кода стоит больше байтов, позже я буду бороться, как его уменьшить.
v=input('');h=numel(v);for i=1:h,f=(v(i)>v(1));l=(v(i)>v(h));for j=h-1:-1:i+1,l=(v(i)>v(j))*(1+l);end,if(i>1),l=l+(v(i)>v(i-1))*l;end;for j=2:i-1,f=(v(i)>v(j))*(1+f);end,if(i<h),f=f+(v(i)>v(i+1))*f;end;s=f+l+1;if(i<h&&i>1),s=s-((v(i)>v(i+1))*(v(i)>v(i-1)));end;s
end

ВХОД

вектор должен иметь форму [abcd ...]

  • пример:

    [2 4 7 11 3]

ВЫХОД

шаблонные случаи.

s =

 1


s =

 2


s =

 3


s =

 8


s =

 1

ОБЪЯСНЕНИЕ:

если [abcd] является входом, программа вычисляет результат ghij как

g = (a> b) + (a> b) (a> c) + (a> b) (a> c) * (a> d) = (a> b) (1+ (a> c) ( 1+ (a> c))))

h = (b> a) + (b> c) + (b> a) (b> c) + (b> c) (b> d) + (b> a) (b> c) (b> d) ) = ... «упрощенный»

i = (c> b) + (c> d) + (c> b) (c> d) + (c> b) (c> a) + (c> d) (c> b) (c> a знак равно

j = (d> c) + (d> c) (d> b) + (d> c) (d> b) * (d> a) = ...


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.