将列表分为大小的块,但不计算不包含谓词的项目


17

动机:有时候列表中的某些项目不会计入您的总数。例如,按排计数飞机乘客,其中婴儿坐在父母的膝盖上。

挑战:编写一个程序将项目列表拆分为多个块。每个块(除了最后一个块)都具有相同的大小,其中size定义为通过谓词函数的项目数。

规则

  1. 您的程序必须
    • 项目清单
    • 正整数块大小
    • 谓词函数(获取一项,并返回true或false)
  2. 您必须返回输入列表,并将其分成多个部分
  3. 每个块都是项目列表
  4. 总体而言,这些物品必须保持相同的顺序,且没有杂物
  5. 每个块(可能是最后一个块除外)中通过谓词的项目数应与输入块大小匹配。
  6. 无法通过谓词的项目不应计入此大小
  7. 谓词失败的项目是
    1. 仍包含在输出块中
    2. 分配给最早的块,如果块“满”,但接下来的项是不通过谓词的项
      • 因此,最终块可能不仅仅包含不符合谓词的项目
  8. 最终块的大小可能小于块大小,因为所有项目都已考虑在内。

非详尽示例:

最简单的示例是考虑1s和0s,其中谓词函数为x ==> x > 0。在这种情况下,sum每个块的都必须与块大小匹配。

  • 项目:[],大小:2,谓词:x > 0-> [][[]]
  • 项目:[0, 0, 0, 0, 0, 0],大小:2,谓词:x > 0->[[0, 0, 0, 0, 0, 0]]
  • 项目:[0, 1, 1, 0],大小:2,谓词:x > 0->[[0, 1, 1, 0]]
  • 项目:[0, 1, 1, 0, 1, 0, 0],大小:2,谓词:x > 0->[[0, 1, 1, 0], [1, 0, 0]]
  • 项目:[0, 1, 0, 0, 1, 0, 1, 1, 0],大小:2,谓词:x > 0->[[0, 1, 0, 0, 1, 0], [1, 1, 0]]

最后,让我们坐上婴儿坐在父母腿上飞机乘客的例子。A成人,b婴儿,飞机排3座位宽,成人总是在婴儿前列出:

  • 项目:[A, b, A, b, A, A, A, b, A, b, A, A, b],大小:3,谓词:x => x == A->[[A, b, A, b, A], [A, A, b, A, b], [A, A, b]]

6
这看起来是一个很好的问题,但目前尚缺乏成功的标准。我建议使用code-golf
Laikoni

3
我们可以假定列表项是单个字符吗?或者说数字?
xnor

分块听起来很有趣,尽管可以用set-partitions代替。
乔纳森·弗雷希

@Laikoni标记了代码高尔夫球
Tom Viner

1
@Ourous我添加了“因为已考虑了所有项目”,即最后一块没有机会获得“满负荷”,因为那只是输入项目的结尾。
汤姆·维纳

Answers:


2

果冻,10 字节

vⱮTm⁵ḊœṖŒṘ

一个完整的程序,该程序将monadic黑盒函数作为第一个可选参数,将列表作为第二个可选参数,将块大小作为第三个可选参数,以打印结果列表的Python表示形式(以避免Jelly隐式粉碎包含字符的列表)。

在线尝试!(请注意,字符列表通过将其格式化为Python引号字符串而传递给Jelly程序)

怎么样?

vⱮTm⁵ḊœṖŒṘ - Main Link: B, L, S
 Ɱ         - map across second argument with (i.e. for X in L):
v          -   evaluate as a monad with input (i.e. B(X))
  T        - truthy indices (e.g. [0,0,1,0,1,1,1,0,0,0,1,0,0]T -> [3,5,6,7,10])
    ⁵      - 3rd optional argument = S
   m       - modulo slice   (e.g. [3,4,7,9,12,15,16,18,19,20]m3 -> [[3,4,7],[9,12,15],[16,18,19],[20]]
     Ḋ     - dequeue        (e.g. [[3,4,7],[9,12,15],[16,18,19],[20]]Ḋ -> [[9,12,15],[16,18,19],[20]]
      œṖ   - partition right (L) at the indices in that
        ŒṘ - print Python representaion

8

Brachylog,37个字节

hW&t~c.k{↰₂ˢl}ᵐ;WxĖ∧.bhᵐ↰₂ᵐ∧.t↰₂ˢl≤W∧

在线尝试!

我很惊讶地发现这-问题的重述-成功终止并产生正确的输出,我感到很惊讶。

假定该谓词在此代码下作为谓词2存在。输出列表列表(“块”),或false输入为空。

说明:

hW&               % First input is W, the expected "weight" of each chunk
                  %  (i.e. the number of items passing predicate in each chunk)

t                 % Take the second input, the list of items
 ~c.              % Output is a partition of this list
    k{    }ᵐ      % For each partition (chunk) except the last, 
      ↰₂ˢ         %   Select the items in the chunk that pass the predicate
         l        %   Get the length of that
                  % (So now we have the list of the "weights" of each chunk)
            ;Wx   % Remove the input expected weight from this list, and 
               Ė  %  the result of this should be empty.
                  %  This verifies that the list of weights is either 
                  %  composed of all W-values, or is empty (when input is [0 0 0] for eg.)

    ∧.bhᵐ↰₂ᵐ      % And, the first element of each chunk (except the first) should
                  %  pass the predicate. This is another way of saying:
                  %  "Items failing the predicate are allocated to the earliest chunk"

    ∧.t↰₂ˢl≤W     % And, the final chunk (which we haven't constrained so far)
                  %  should have weight ≤ the input expected weight
                  %  This disallows putting everything in the final chunk and calling it a day!

    ∧             % (no further constraints on output)

7

Apl(Dyalog Unicode) 17 16字节(SBCS)

感谢Adám为我节省了1个字节。

w⊆⍨⌈⎕÷⍨1⌈+\⎕¨w←⎕

在线尝试! 为了说明起见,我将放弃17字节的解决方案。

{⍵⊆⍨⌈⍺÷⍨1⌈+\⍺⍺¨⍵}

⍺⍺¨⍵aplies谓词到列表中返回一个布尔矢量
+\生成的运行总计
1⌈内容替换主导0s的1小号
⌈⍺÷⍨除以块大小和上舍入每个元素
⍵⊆⍨由该分区的原始矢量


2
这很让人佩服!而且我喜欢输出显示,适合该问题的视觉显示。
sundar-恢复莫妮卡

通过转换为程序(tradfn体)保存一个字节:w⊆⍨⌈⎕÷⍨1⌈+\⎕¨w←⎕
ADAM

5

干净96 92个字节

使用f :: a -> Bool根据元共识允许的命名函数。

import StdEnv,StdLib
$l n|l>[]=last[[i: $t n]\\i<-inits l&t<-tails l|n>=sum[1\\e<-i|f e]]=[]

在线尝试!

展开(默认高亮显示评论):

$ l n // define function $ on `l` and `n`
 | l > [] // if `l` is not the empty list
  = last [ // the last element of ...
                   \\ i <- inits l // prefixes of `l`
                    & t <- tails l // matching suffixes of `l`
                    | n >= // where n is greater than or equal to
                           sum [1 \\ e <- i | f e] // the number of matching elements in the prefix
          [i: $t n] // prepend that prefix to the application of $ to the rest of the list
         ]
 = [] // if `l` is empty, return empty

4

Java的10,207个 186 159 148字节

a->n->{var r=new java.util.Stack();int l=a.size(),i=0,c=0,j=0;for(;i<=l;i++)if(i==l||f(a.get(i))&&++c>n&i>0){r.add(a.subList(j,j=i));c=1;}return r;}

Java绝对不是解决此挑战的正确语言(或者当然是任何代码挑战)。

-21个字节,感谢@OOBalance

在线尝试。

说明:

a->n->{                    // Method with List & int parameters & List of Lists return-type
  var r=new java.util.Stack();
                           //  Result-list, starting empty
  int l=a.size(),          //  Size of the input-List
      c=0,                 //  Count-integer, starting at 0
      j=0,                 //  Range-integer, starting at 0
  i=0;for(;i<=l;i++){      //  Loop `i` in the range [0, `l`]
    if(i==l||              //   If this is the last iteration
       f(a.get(i))         //   Or if the black-box function is true for the current item
       &&++c               //    Increase the counter by 1
        >n&                //    If the counter is now larger than the size
        &i>0){             //    and it's not the first item of the List
      a.subList(j,j=i);    //     Add a sub-List to the result from range [`j`, `i`)
                           //     And set `j` to `i` at the same time
      c=1;}                //     And reset `c` to 1
  return r;}               //  Return the List of Lists as result

黑匣子输入格式:

假设存在一个命名函数boolean f(Object i)根据此meta答案可以使用

我有一个Test包含默认函数f(i)以及上面的lambda 的抽象类:

abstract class Test{
  boolean f(Object i){
    return true;
  }

  public java.util.function.Function<java.util.List, java.util.function.Function<Integer, java.util.List<java.util.List>>> c =
    a->n->{var r=new java.util.Stack();int l=a.size(),i=0,c=0,j=0;for(;i<=l;i++)if(i==l||f(a.get(i))&&++c>n&i>0){r.add(a.subList(j,j=i));c=1;}return r;}
  ;
}

对于测试用例,我将覆盖此函数f。例如,最后一个测试用例的调用如下:

System.out.println(new Test(){
  @Override
  boolean f(Object i){
    return (char)i == 'A';
  }
}.c.apply(new java.util.ArrayList(java.util.Arrays.asList('A', 'b', 'A', 'b', 'A', 'A', 'A', 'b', 'A', 'b', 'A', 'A', 'b'))).apply(3));

1
(or any codegolf-challenge of course..)“嗯,我不知道,您至少在某些情况下击败了我的“干净”答案。无论如何,我一直期待着您的答复。
Οurous

2
@OOurous Java绝不适合代码高尔夫,这是一个模因,如果我们将它与实际的高尔夫语言(如Jelly,05AB1E等)进行比较,我想Java也适用于Clean。我仍然喜欢解决所有这些代码高尔夫挑战但是在Java中(我也假设您在Clean中)。而且(很长一段时间),Java就能击败Python。;)我曾经是Java的领先者,直到bash破坏了它(R进一步打了球)。xD
Kevin Cruijssen '18

1
如果返回数组列表,则为186个字节:bit.ly/2mSjCIc
OOBalance

@OOBalance谢谢!聪明使用Arrays.copyOfRange
凯文·克鲁伊森

通过将输入作为List并使用,@ OOBalance可以进行更多地高尔夫运动.sublist。除此之外,您的功能保持不变,但是它节省了大量字节并删除了导入。(现在它也适用于用字符而不是整数的测试用例。)
Kevin Cruijssen


3

C(gcc)70 66字节

我使用一种结构来记下子列表的开头,因为C对此一无所知。

感谢天花板猫的建议。

t;f(a,s,c)l*a;int(*c)();{for(;a->v;a++)(t+=c(a->v))>s?t=++a->s:0;}

在线尝试!


3

Haskell,72个字节

p#s|let l@(h:t)!a|sum[1|e<-h:a,p e]>s=a:l![]|n<-a++[h]=t!n;_!a=[a]=(![])

在线尝试!

p#s     = (![])         -- main function that takes a predicate function 'p',
                        -- a size 's' and a input list without a name that is
                        -- directly passed as the first argument to function '!'
  let  l@(h:t)!a        -- function '!' is a local function (so that 'p' and 's'
                        -- are in scope). Takes a list 'l' of at least one element
                        -- 'h' (and 't' being the rest of the list) and an
                        -- accumulator 'a'
   |sum[1|e<-h:a,p e]>s -- if 'p' holds for more than 's' elements in 'h' and 'a'
     =a:l![]            --   put 'a' in front of a recursive call with the same list
                        --   'l' and an empty accumulator
   |n<-a++[h]           -- else bind 'n' to 'h' appended to 'a' and
     =t!n               --   call '!' again with 't' and 'n'
  _!a=[a]               -- base case for '!'. If the input list is empty, return
                        --   a singleton list with 'a' 

3

MATL,19个字节

HyX$Ysi/Xk1y>+!w7XQ

基于jslip出色的APL答案

MATL实际上并没有用户定义的函数,但是它确实有一种方法可以调用其运行的环境(MATLAB / Octave),因此将其用于谓词函数。用法可能像这样,但是出于安全原因在线禁用了该功能,因此以下是使用硬编码isodd谓词功能的版本:在MATL Online上尝试

H    % Push the function name to be called, assumed to be 
     %  stored in the H clipboard
y    % Take the first input, push copies of it both below and above the 
     %  function name
X$   % Call the function (say 'isupper') with the input as argument
     %  returns a boolean vector
Ys   % Cumulative sum
i/   % Take the chunk size and divide each element by it
Xk   % ceil
1y>+ % Turn the (initial) 0s to 1s
!    % Transpose. Now we have a column vector specifying which chunk 
     %  each input element should go into
w    % Bring the other copy of the input on top 
7    % Code for this function: '@(x){x.'}'
     %  i.e. place each chunk in a row vector and enclose it in a cell
XQ   % 'accumarray' - split the input into chunks based on
     %   the given column vector, apply the given function to each chunk
     %   (which here just wraps it up as a cell), and accumulate the results
     %   in an array.
     % implicit output


2

红宝石,57个字节

->a,n,g{c=-1;a.group_by{|x|[0,c+=g[x]?1:0].max/n}.values}

在线尝试!

匿名lambda接受输入数组a,块大小n和谓词g。维护c与谓词匹配的项的计数器,并按已用完的块数对项进行分组。不幸的是,初始值-1 / n不能四舍五入,因此我们必须花费一些字节来修复它。





1

Mathematica,82个字节

f[l_,s_,p_]:=Last@Reap[i=t=-1;Do[If[p@e,If[++i~Mod~s==0&&i>0,t++]];e~Sow~t,{e,l}]]

取消高尔夫:

f[l_,s_,p_] :=                (* define a function that takes three    *)
                              (* arguments                             *)

  Last@Reap[                  (* collect and return results which were *)
                              (* gathered by the procedural loop below *)

    i=t=-1;                   (* initialize two counters               *)

    Do[                       (* start iterating over the list         *)

      If[p@e,                 (* if element passes predicate           *)
        If[                   (* then if preincremented i is 0 modulo  *)
          ++i~Mod~s==0&&i>0,  (* chunk size and i > 0                  *)
          t++                 (* increment t                           *)
        ]
      ];e~Sow~t,              (* finally sow the element tagged with   *)
                              (* the current value of t                *)

    {e,l}]                    (* e references current element of list  *)
                              (* l is the list itself                  *)
  ]

l是输入列表;s是块大小;p是一个未命名/匿名/纯/ lambda函数,可对列表的元素进行操作,返回true / false。

Last@Reap[...]返回。Sow内部的-n 的每个元素的列表列表...。它们的第二个参数e~Sow~t是的缩写,它们被分组为子列表Sow[e, t]

我必须将计数器初始化为-1以处理1的块大小,否则我将需要检查Mod[i, s]i~Mod~s)等于1,这永远不会发生。

其余代码在ungolfed块中进行了说明。

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.