不相邻项目的最大合计子序列


23

介绍:

由这两个问题SO(没有来自同一类怀疑)的启发:打印不相邻的元件的java在最大总和的子阵列的元件阵列的非相邻元件的最大总和,将被打印

挑战:

给定一个整数列表,输出由具有最高和的不相邻元素组成的子序列。这里有一些例子:

  • [1,2,3,-1,-3,2,5]将导致基于0的索引处[1,3,5](总和为9[0,2,6]
  • [4,5,4,3]会在基于0的索引处产生[4,4](总和8),[0,2]或者在基于0的索引处产生[5,3](总和8[1,3]
  • [5,5,10,100,10,5]会导致基于0的索引或产生[5,100,5](总和110)。[0,3,5][1,3,5]

上面这些示例中最重要的是,包含元素的索引彼此之间至少相距2。如果我们[5,5,10,100,10,5]更深入地看这个例子:我们有以下包含不相邻项的潜在子序列;索引低于它;其总和如下:

[[5],[10],[100],[10],[5],[5],[100,5],[10,5],[10,10],[5,5],[5,10],[5,100],[5,5],[5,10],[5,100],[5,10],[5,100,5],[5,100,5],[5,10,5],[5,10,10]]   // non-adjacent subsequences
[[5],[ 4],[  3],[ 2],[1],[0],[  3,5],[ 2,5],[ 2, 4],[1,5],[1, 4],[1,  3],[0,5],[0, 4],[0,  3],[0, 2],[1,  3,5],[0,  3,5],[0, 2,5],[0, 2, 4]]   // at these 0-based indices
[  5,  10,  100,  10,  5,  5,    105,    15,     20,   10,    15,    105,   10,    15,    105,    15,      110,      110,      20,       25]   // with these sums
                                                                                                            ^         ^                        // and these two maximums

由于最大和为110,因此我们[5,100,5]将结果输出。

挑战规则:

  • 您可以输出索引+值的键/值对。因此,[5,100,5]您可以输出[[0,5],[3,100],[5,5]][[1,5],[3,100],[5,5]]作为结果(或[[1,5],[4,100],[6,5]]/ [[2,5],[4,100],[6,5]]当使用基于1的索引而不是基于0的索引时)。
    • 如果您使用键值对,它们也可以相反或随机排列,因为很明显哪个值是由于成对索引引起的。
    • 不允许仅输出没有值的索引。它应该输出值,或者将值/索引作为键值对输出(或者,如果您选择的语言无法使用键值对,则应将两个相同大小的“键”和“值”的单独列表输出)。
  • 您可以输出最大和而不是一个最大的所有可能子序列。
  • 从示例中可以看到,输入列表也可以包含负值和重复值。你可以假设输入整数是该范围内[999,999]
  • output-list不能为空,并且必须始终包含至少一个元素(如果列表仅包含负值,则包含单个最低负值的列表将作为结果输出-请参阅最后两个测试用例)。
  • 如果存在一个可能的输出,但对于多个不同的索引,则即使它们看起来可能重复,也允许输出它们两者。(即上面的示例,可以[[5,100,5],[5,100,5]]为两种可能的索引组合输出)。

测试用例:

Input:                   Possible outputs:       At 0-based indices:     With sum:

[1,2,3,-1,-3,2,5]        [1,3,5]                 [0,2,6]                 9
[4,5,4,3]                [4,4]/[5,3]             [0,2]/[1,3]             8
[5,5,10,100,10,5]        [5,100,5]               [0,3,5]/[1,3,5]         110
[10]                     [10]                    [0]                     10
[1,1,1]                  [1,1]                   [0,2]                   2
[-3,7,4,-2,4]            [7,4]                   [1,4]                   11
[1,7,4,-2]               [7]                     [1]                     7
[1,2,-3,-4,5,6,-7]       [2,6]                   [1,5]                   8
[800,-31,0,0,421,726]    [800,726]/[800,0,726]   [0,5]/[0,3,5]/[0,2,5]   1526
[-1,7,8,-5,40,40]        [8,40]                  [2,4]/[2,5]             48
[-5,-18,-3,-1,-10]       [-1]                    [3]                     -1
[0,-3,-41,0,-99,-2,0]    [0]/[0,0]/[0,0,0]       [0]/[3]/[6]/[0,3]/
                                                  [0,6],[3,6]/[0,3,6]    0

如果有多个相同的集合(但来自不同的索引),可以列出所有这些集合吗?例如[5,100,5],您的第三个示例两次。
尼克·肯尼迪

1
powerset是一组子集吗?但看起来您正在返回一组子序列?[4,5,4,3]将导致[4,4]中的任何一个,其中[4,4]显然不是集合。
过期的数据

1
@Arnauld是的,如果值是带有索引的键值对,则可以清楚知道输入中要包含哪些索引值,因此它们可以以任何顺序排列。还将其编辑为挑战说明。
凯文·克鲁伊森

2
只是要确保:输出索引不是一种选择,是吗?
毛茸茸的

1
经典术语是“子序列”。但是,这具有人们想到连续子序列的相同问题。如果我们实际上在这里使用集合,我会说“子集”,但是这些绝对是序列-顺序和重复项是允许的。
user2357112支持Monica

Answers:


6

外壳,11个字节

►Σ†!¹mü≈tṖŀ

在线尝试!

说明

►Σ†!¹mü≈tṖŀ  Implicit input, say L=[4,5,3,4].
          ŀ  Indices: [1,2,3,4]
         Ṗ   Powerset: [[],[1],[2],[1,2],..,[1,2,3,4]]
        t    Tail (remove the empty list): [[1],[2],[1,2],..,[1,2,3,4]]
     m       For each,
      ü      de-duplicate by
       ≈     differing by at most 1.
             For example, [1,2,4] becomes [1,4].
  †          Deep map
   !¹        indexing into L: [[4],[5],[4],..,[5,4],[4,3]]
►            Maximum by
 Σ           sum: [5,4]

6

Haskell,60个字节

snd.([]%)
r%(h:t)=max(r%t)$(r++[h])%drop 1t
r%_=(sum r<$r,r)

在线尝试!

辅助功能 %递归方式选择包含第一个元素并删除第二个元素,还是跳过第一个元素。它采用所有结果中的最大值,这些结果是元组,其第一个元素是和,而第二个元素是为输出提取的对应列表。

为了处理该空列表是不允许的,即使它会具有最小招规则,我们确实写的一个可爱的把戏sum r<$r,而不是sum r。这使得所有元素均是一个列表sum r,其长度是的r。这样,当我们选择最大值时,我们将所有列表的优先级排在一个空的优先级上r,但否则比较取决于第一个元素()sum r


6

R136125字节

function(l,G=unlist(Map(combn,list(y<-seq(a=l)),y,c(function(x)'if'(all(diff(x)>1),l[x],-Inf)),F),F))G[which.max(Map(sum,G))]

在线尝试!

-6个字节要感谢digEmAll,他也顺便超过了我

以a的形式返回最短的子序列list,在字典上首先由索引打破联系。

蛮力生成所有索引子序列,然后Filter为不相邻的子序列(即)生成s all(diff(x)>1)。然后子集[l使用这些指标,选择[[第一个,其中的总和为最大(which.max)。

我很确定这是我编写的第一个使用R的答案Filter伤心,Filter太笨拙了,难怪我从来没有用过...



@digEmAll谢谢!
朱塞佩

5

05AB1E,14个字节

感谢Kevin Cruijssen节省了1个字节

ā<æʒĆ¥≠W}èΣO}θ

在线尝试! 或作为测试套件

说明

ā<               # push [0 ... len(input)-1]
  æ              # compute powerset
   ʒ    }        # filter, keep lists where:
      ≠W         # no element is 1 in the
     ¥           # deltas
    Ć            # of the list with the head appended
         è       # index into the input with each
          ΣO}    # sort by sum
             θ   # take the last element

您可能不满意,但比我最初的解决方案还短4个字节。;),您还可以将1换¤ªĆ
凯文·克鲁伊森

@KevinCruijssen:哦,是的!由于某种原因,我已经说服自己自己最后需要重复一个元素。谢谢!
Emigna

5

Brachylog(v2),14个字节

{~ba~c∋₁ᵐ}ᶠ+ᵒt

在线尝试!

功能提交;与往常一样,从左侧输入,从右侧输出。非常慢; 一个五元素列表可能是在TIO上进行测试的最大数量。

{~ba~c∋₁ᵐ}ᶠ+ᵒt
 ~b              Prepend an arbitrary element to the input
   a             Take a prefix or suffix of the resulting list
    ~c           Ordered partition into contiguous sublists
      ∋₁         Take the second element
        ᵐ          of each sublist
{        }ᶠ      Find all possible ways to do this
           +ᵒ    Sort by sum
             t   Take the greatest

我们从前缀得到的结果不是不正确,但也不是很有趣。所有可能的结果都是通过带一个后缀(可能是列表本身,但不能为空)生成的,但是在Brachylog中,“后缀”比“前缀或后缀”更为冗长,因此我使用的是terser(以及更少的版本)高效但仍然正确)。基本思想是,对于输出列表中我们想要的每个元素,将其划分为连续的子列表都需要将该元素和之前的元素放入同一子列表中(因为该元素是第二个子列表的元素),因此结果中不会出现两个连续的元素。另一方面,很明显,没有两个连续元素的任何列表都可以出现在结果中。因此,一旦有了所有可能的候选者列表,我们就可以将它们全部求和,然后看看哪个是最大的。



3

的JavaScript(ES6), 138个132 130 129  126字节

输出键值对。

a=>a.reduce((a,x,i)=>[...a,...a.map(y=>[[x,i],...y])],[[]]).map(m=a=>a.some(s=p=([v,i])=>p-(s=~~s+v,p=i)<2)|s<m||(r=a,m=s))&&r

在线尝试!

步骤1

[v一种üË一世ñdËX]

a.reduce((a, x, i) => // for each value x at position i:
  [                   //   update a[] to a new array consisting of:
    ...a,             //     all previous entries
    ...a.map(y =>     //     for each value y in a[]:
      [[x, i], ...y]  //       append [x, i], followed by all original entries
    )                 //     end of map()
  ],                  //   end of new array
  [[]]                //   start with a = [[]]
)                     // end of reduce()

第2步

[R

.map(m =              // initialize m to a non-numeric value
  a =>                // for each entry a[] in the powerset:
  a.some(s = p =      //   initialize s and p to non numeric values
    ([v, i]) =>       //   for each value v and each index i in a[]:
    p - (             //     compute p - i
      s = ~~s + v,    //     add v to s
      p = i           //     update p to i
    ) < 2             //     if p - i is less than 2, yield true
  ) |                 //   end of some()
  s < m ||            //   unless some() was truthy or s is less than m,
  (r = a, m = s)      //   save a[] in r[] and update m to s
) && r                // end of map(); return r[]

3

Haskell,81个 80字节

snd.maximum.map((,)=<<sum).tail.f
f(a:b:c)=f(b:c)++map(a:)(f c)
f a=[]:map(:[])a

在线尝试!

f通过跳过下一个元素(f(b:c))或使用它并跳过下一个(map(a:)(f c))来构建所有有效的子序列,然后递归地处理其余子序列。为了得到结果,构建所有子序列(f),删除空的子序列(在列表中首先出现tail),进行成对(<sum>,<subsequence>)map((,)=<<sum)),找到最大值(成对以字典顺序比较)-> maximum),然后删除总和(snd)。

编辑:-1字节感谢@Lynn。


1
map(:[])a是比(pure<$>a)^^ 短的字节
Lynn


3

T-SQL, 122个 119 118字节

输入是一个表变量。

该查询从表变量中选择所有元素,并将其与所有具有较高位置值的非相邻元素组合在一起,并显示为这些值的最高总和生成的文本。

WITH C(y,j,v)as(SELECT*,x*1FROM @
UNION ALL
SELECT y+','+x,i,v+x
FROM @ JOIN C ON~-i>j)SELECT
TOP 1y FROM C ORDER BY-v

在线试用



2

Pyth,19个字节

esDm@LQdtf!q#1.+TyU

在此处在线尝试,或在此处一次验证所有测试用例。

esDm@LQdtf!q#1.+TyUQ   Implicit: Q=eval(input())
                       Trailing Q inferred
                  UQ   Generate range [0-len(Q))
                 y     Take the powerset of the above
         f             Filter keep elements of the above, as T, using:
              .+T        Take differences of consecutive elements of T
           q#1           Keep those differences equal to 1
          !              Logical NOT - empty lists evaluate to true, populated ones to false
                       Result of the filter is those sets without consecutive numbers
        t              Drop the first element (empty set)
   m                   Map the remaining sets, as d, using:
     L d                 For each element of d...
    @ Q                  ... get the element in Q with that index
 sD                    Order the sets by their sum
e                      Take the last element, implicit print

2

盖亚(Gaia),24个字节

e:w;ċz⟨ọ1>¦ẏ⟩⁇‼⁇E‡ev2%Σ⌠

在线尝试!

唉,E‡做一些奇怪的东西......根据文档,它应该像做“给定长度i组列表X和长度j索引集Y,回归X[i][Y[j]]”,而是返回[X[i][Y[j]] X[i][Y[-j]]其中负索引代表补充,所以我们要做的ev2%到仅提取我们想要的。

e				| eval as a list l
 :				| dup
  w				| wrap as a list
   ;				| push l again
    ċ				| push [1..len(l)]
     z				| push all subsets of [1..len(l)] -- index powerset.
      ⟨      ⟩⁇			| filter this for:
       ọ			| deltas
        1>¦			| are greater than 1
           ẏ			| all (all deltas greater than 1)
	       ‼⁇		| filter for non-empty lists
		 E‡		| table extract elements. Given l and index set i, this pushes
				| [l[i] l[setdiff(1..l,i)]] for some reason
		   ev2%		| get the l[i] only by unlisting, reversing, and taking every other element
		       Σ⌠	| Get the one with the maximum sum

出于好奇,为什么输出有两个尾随]]而不是一个?
Kevin Cruijssen

@KevinCruijssen口译员的另一个有趣的怪癖;所有列表都是这样打印出来的,因此要[[1] [2]]进行打印[[1]] [2]]]],这使得读取/调试列表输出变得非常困难。
朱塞佩

认为这是因为re.sub(" ?$","]",result)解释器中的表达式应该改为,re.sub(" +$","]",result)但我的python非常糟糕。
朱塞佩

2

[R 108个 107字节

function(v,M=-Inf){for(j in J<-seq(a=v))for(i in combn(J,j,,F))if(all(diff(i)>1)&sum(v[i])>sum(M))M=v[i]
M}

在线尝试!

-1感谢@Giuseppe


2

Wolfram语言(Mathematica)70 63字节

MaximalBy[Select[q=Rest@Subsets@#,!FreeQ[q,#~Riffle~_]&],Tr,1]&

在线尝试!

高级搜索

          Select[q=Rest@Subsets@#,                     ]        (*choose nonempty subsets of the input such that*)
                                  !FreeQ[q,          ]&         (*there exists a subset of the input which matches*)
                                           #~Riffle~_           (*this list, with an item inserted between adjacent elements*)
MaximalBy[                                              ,Tr,1]& (*and return one with the greatest total*)

,1是必需的,以免无意中返回无效的集合(否则,例如,输入{1,1,1}会导致的输出{{1,1},{1,1},{1,1}}


1

哈斯克尔300个 168字节

import Data.List
h[]=1>2
h(x:y)=fst$foldl(\a c->((fst a)&&(c-snd a>1),c))(1<2,x)y
z=snd.last.sortOn fst.map((,)=<<sum.snd).filter(h.fst).map unzip.subsequences.zip[0..]

在线尝试!

-132字节感谢@nimi的所有反馈:)


原版的

无高尔夫球(原始)

import Data.List
import Data.Function

f :: [Int] -> [(Int, Int)] -- attach indices for later use
f [] = []
f xs = zip xs [0..length xs]

g :: [[(Int, Int)]] -> [([Int], [Int])] -- rearrange into list of tuples
g [] = []
g (x:xs) = (map fst x, map snd x) : g xs

h :: [Int] -> Bool -- predicate that checks if the indices are at least 2 apart from each other
h [] = False
h (x:xs) = fst $ foldl (\acc curr -> ((fst acc) && (curr - snd acc > 1), curr)) (True, x) xs
j :: [([Int], [Int])] -> [([Int], [Int])] -- remove sets that don't satisfy the condition
j xs = filter (\(elements, indices) -> h indices) xs

k :: [([Int], [Int])] -> [(Int, ([Int], [Int]))] -- calculate some of elements
k xs = map (\(elements, indices) -> (foldl1 (+) elements, (elements, indices))) xs

l :: [(Int, ([Int], [Int]))] -> ([Int], [Int]) -- grab max
l xs = snd $ last $ sortBy (compare `on` fst) xs

z -- put things together
```

1
一些提示:在f:返回的对中翻转元素及其索引f x=zip[0..length x]x,因此f成为f=zip[0..]g就是g=map unzip。使用in进行过滤的功能jh.fst(<-翻转对!)。j=filter(h.fst)。的foldl1+ksum并用一对pointfree制作k=map((,)=<<sum.snd)sortBy(...)可以替换为sortOn fstl=snd.last.sortOn fst。:最后,你正在使用的所有功能只有一次,你可以内联成一个单一的pointfree表达z=snd.last.sortOn fst.map((,)=<<sum.snd).filter(h.fst).map unzip.subsequences.zip[0..]
NIMI


哦,不再需要导入Data.Function了。
nimi

太好了,谢谢您的反馈:)
bugs

下一步h:我们正在寻找不相邻的元素,即相邻索引的差必须为>1zipWith(-)=<<tail构建这样的差异列表,但是对于空列表却失败了,因此我们需要附加tail一个subsequences来消除它。再次内联。在线尝试!
nimi

1

木炭,46字节

≔⟦υ⟧ηFθ«≔υζ≔Eη⁺κ⟦ι⟧υ≔⁺ζηη»≔Φ⁺υηιη≔EηΣιζI§η⌕ζ⌈ζ

在线尝试!链接是详细版本的代码。说明:

≔⟦υ⟧η

该变量u预定义为空列表。这放在分配给的列表中h。这些变量充当累加器。u包含包含输入最新元素的子列表,qh包含不包含最新子元素的子列表(因此适合附加输入的下一个元素)。

Fθ«

循环输入的元素。

≔υζ

保存包含上一个元素的子列表的列表。

≔Eη⁺κ⟦ι⟧υ

取得所有不包含前一个元素的子列表,追加当前元素,然后将结果保存为包含当前元素的子列表。(我不使用Push这里,因为我需要克隆列表。)

≔⁺ζηη»

将之前的两个子列表连接到不包含当前元素的新子列表中。

≔Φ⁺υηιη

最后一次连接子列表,并删除原始的空列表(无论如何木炭总不能)。

≔EηΣιζ

计算所有子列表的总和。

I§η⌕ζ⌈ζ

查找最大和的索引并输出相应的子列表。



1

杰普特 -h,21字节

您曾经完全忘记打高尔夫球的挑战之一吗?

ð¤à fÊk_än ø1îmgUÃñx

试试吧

ð¤à fÊk_än ø1îmgUÃñx     :Implicit input of array U
ð                         :Indices of elements that return true when
 ¤                        :  Converted to a base-2 string (to account for 0s)
  à                       :Combinations
    f                     :Filter by
     Ê                    :  Length (to remove the empty combination)
      k_                  :Remove elements that return true
        än                :  Deltas
           ø1             :  Contains 1
             Ã            :End remove
              ®           :Map
               m          :  Map
                gU        :    Index into U
                  Ã       :End map
                   ñ      :Sort by
                    x     :  Sum
                          :Implicit output of last element

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.