Membagi daftar menjadi potongan berukuran, tetapi tidak termasuk item yang gagal mendapatkan predikat

17

Motivasi : Terkadang item tertentu dalam daftar tidak dihitung terhadap total Anda. Misalnya, menghitung penumpang pesawat dalam barisan, di mana bayi duduk di pangkuan orang tua.

Tantangan : menulis sebuah program untuk membagi daftar item menjadi potongan-potongan. Setiap potongan (kecuali mungkin yang terakhir) adalah ukuran yang sama , di mana ukuran didefinisikan sebagai jumlah item yang melewati fungsi predikat.

Aturan :

  1. Program Anda harus ambil
    • daftar barang
    • ukuran bilangan bulat positif
    • fungsi predikat (mengambil item, dan mengembalikan benar atau salah)
  2. Anda harus mengembalikan daftar input yang dipecah menjadi beberapa bagian
  3. Setiap chunk adalah daftar item
  4. Secara keseluruhan barang harus tetap dalam urutan yang sama, tanpa ada yang dibuang
  5. Jumlah item yang melewati predikat di setiap chunk (kecuali mungkin yang terakhir) harus sesuai dengan ukuran chunk input.
  6. item yang gagal predikat seharusnya tidak diperhitungkan dalam ukuran ini
  7. Item yang gagal predikatnya adalah
    1. masih termasuk dalam potongan output
    2. dialokasikan ke chunk paling awal, dalam hal chunk adalah "penuh" tetapi item berikutnya adalah yang gagal predikat
      • jadi potongan terakhir mungkin tidak hanya terdiri dari barang-barang yang gagal dengan predikat
  8. Potongan terakhir mungkin berukuran kurang dari ukuran potongan karena semua item telah diperhitungkan.

Contoh tidak lengkap:

Contoh paling sederhana adalah untuk mempertimbangkan 1s dan 0s, di mana fungsi predikat berada x ==> x > 0. Dalam hal ini, sumsetiap chunk harus cocok dengan ukuran chunk.

  • item:, []ukuran 2:, predikat: x > 0-> salah satu []atau[[]]
  • item:, [0, 0, 0, 0, 0, 0]ukuran 2:, predikat: x > 0->[[0, 0, 0, 0, 0, 0]]
  • item:, [0, 1, 1, 0]ukuran 2:, predikat: x > 0->[[0, 1, 1, 0]]
  • item:, [0, 1, 1, 0, 1, 0, 0]ukuran 2:, predikat: x > 0->[[0, 1, 1, 0], [1, 0, 0]]
  • item:, [0, 1, 0, 0, 1, 0, 1, 1, 0]ukuran 2:, predikat: x > 0->[[0, 1, 0, 0, 1, 0], [1, 1, 0]]

Dan mari kita selesaikan dengan penumpang pesawat di mana bayi duduk di pangkuan orang tua . Auntuk orang dewasa, buntuk bayi, baris pesawat adalah 3kursi lebar, orang dewasa selalu terdaftar sebelum bayi mereka:

  • item:, [A, b, A, b, A, A, A, b, A, b, A, A, b]ukuran 3:, predikat: x => x == A->[[A, b, A, b, A], [A, A, b, A, b], [A, A, b]]
Tom Viner
sumber
6
Ini sepertinya pertanyaan yang bagus, tetapi saat ini tidak memiliki kriteria kemenangan. Saya sarankan menggunakan kode-golf .
Laikoni
3
Bisakah kita menganggap item daftar adalah karakter tunggal? Atau, katakanlah, angka?
xnor
bungkusan terdengar menarik, meskipun mungkin bisa diganti dengan set-partisi .
Jonathan Frech
@Laikoni memberi tag kode-golf
Tom Viner
1
@Ourous Saya telah menambahkan "karena semua item telah diperhitungkan", yaitu potongan terakhir tidak mendapatkan kesempatan untuk mendapatkan "penuh", karena itu hanyalah akhir dari item input.
Tom Viner

Jawaban:

2

Jelly , 10 byte

vⱮTm⁵ḊœṖŒṘ

Program lengkap yang menggunakan fungsi kotak hitam monadik sebagai argumen opsional pertama, daftar sebagai argumen opsional kedua dan ukuran chunk sebagai argumen opsional ketiga yang mencetak representasi Python dari daftar daftar yang dihasilkan (untuk menghindari penghancuran implisit Jelly dari daftar yang berisi karakter).

Cobalah online! (perhatikan bahwa daftar karakter diteruskan ke program Jelly dengan memformatnya sebagai string yang dikutip Python)

Bagaimana?

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
Jonathan Allan
sumber
8

Brachylog , 37 byte

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

Cobalah online!

Saya terkejut menemukan bahwa ini - cukup banyak pernyataan kembali - berhasil berakhir dan menghasilkan output yang benar.

Asumsikan predikat 2 hadir sebagai predikat di bawah kode ini. Mengeluarkan daftar daftar ("bongkahan"), atau falseuntuk input kosong.

Penjelasan:

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)
sundar - Pasang kembali Monica
sumber
7

Apl (Dyalog Unicode) 17 16 byte (SBCS)

Terima kasih Adám karena telah menyelamatkan saya 1 byte.

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

Cobalah online! untuk tujuan penjelasan saya akan meninggalkan solusi 17 byte.

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

⍺⍺¨⍵aplies predikat ke dalam daftar mengembalikan vektor boolean
+\menghasilkan menjalankan keseluruhan
1⌈Menggantikan terkemuka 0s dengan 1s
⌈⍺÷⍨membagi setiap elemen dengan ukuran potongan dan putaran up
⍵⊆⍨ partisi vektor asli oleh ini

jslip
sumber
2
Itu mengesankan! Dan saya suka tampilan keluaran, visual yang sesuai untuk masalahnya.
sundar - Reinstate Monica
Simpan satu byte dengan mengonversi ke program (tradfn body):w⊆⍨⌈⎕÷⍨1⌈+\⎕¨w←⎕
Adám
5

Bersih , 96 92 byte

Menggunakan fungsi bernama yang f :: a -> Booldiizinkan sesuai dengan konsensus meta.

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

Cobalah online!

Diperluas (dengan penyorotan default untuk membuat komentar muncul):

$ 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
Suram
sumber
4

Java 10, 207 186 159 148 byte

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 jelas bukan bahasa yang tepat untuk tantangan ini (atau tantangan codegolf apa pun tentu saja ..)

-21 byte berkat @OOBalance

Cobalah online.

Penjelasan:

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

Format input kotak hitam:

Asumsikan ada fungsi bernama boolean f(Object i), yang diizinkan sesuai dengan jawaban meta ini .

Saya memiliki kelas abstrak yang Testberisi fungsi default f(i), serta lambda di atas:

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;}
  ;
}

Untuk kasus uji, saya menimpa fungsi ini f. Sebagai contoh, test case terakhir disebut seperti ini:

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));
Kevin Cruijssen
sumber
1
" (or any codegolf-challenge of course..)" ehh, entahlah, Anda sudah mengalahkan jawaban Bersih saya setidaknya dalam beberapa kasus. Bagaimanapun, saya selalu menantikan jawaban Anda.
Οurous
2
@ Οurous Ini lebih dari sebuah meme bahwa Java tidak cocok untuk codegolf dengan cara apa pun, yang saya kira berlaku untuk Bersihkan juga jika kita membandingkannya dengan bahasa golf aktual seperti Jelly, 05AB1E, dll. Saya masih menikmati menyelesaikan semua tantangan codegolf ini di Jawa (dan Anda dalam Bersihkan juga saya berasumsi). Dan sesekali (lama), Java mampu mengalahkan Python . ;) Dan saya pernah menjadi jawaban terkemuka dengan Java , sampai bash merusaknya (dan R bermain golf lebih lanjut). xD
Kevin Cruijssen
1
186 byte jika Anda mengembalikan Daftar array: bit.ly/2mSjCIc
OOBalance
@Oalkalan Terima kasih! Penggunaan cerdas Arrays.copyOfRange!
Kevin Cruijssen
@OOBalance bisa bermain golf lebih banyak dengan menggunakan input sebagai Daftar dan menggunakan .sublist. Fungsionalitas Anda tetap sama, tetapi menyimpan banyak byte dan menghapus impor. (Dan sekarang ini juga berfungsi untuk kasus uji dengan karakter bukan bilangan bulat.)
Kevin Cruijssen
4

R , 58 byte

function(v,g,n,a=(cumsum(Map(g,v))-1)%/%n)split(v,a*(a>0))

Cobalah online!

  • -5 byte terima kasih kepada @Giuseppe
menggali semua
sumber
1
58 bytes
Giuseppe
3

C (gcc) , 70 66 byte

Saya menggunakan struktur untuk mencatat awal sub-daftar, karena C tidak tahu tentang hal-hal seperti itu.

Terima kasih kepada ceilingcat untuk sarannya.

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

Cobalah online!

ErikF
sumber
3

Haskell, 72 byte

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

Cobalah online!

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' 
nimi
sumber
3

MATL, 19 byte

HyX$Ysi/Xk1y>+!w7XQ

Berdasarkan jawaban APL yang sangat baik dari jslip .

MATL tidak benar-benar memiliki fungsi yang ditentukan pengguna seperti itu, tetapi ia memiliki cara untuk memanggil ke lingkungan yang sedang berjalan (MATLAB / Oktaf), jadi ini menggunakan itu untuk fungsi predikat. Penggunaan akan menjadi seperti ini , tetapi fungsionalitas itu dinonaktifkan online karena alasan keamanan, jadi inilah versi yang menggunakan isoddfungsi predikat hardcoded sebagai gantinya: Cobalah di 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
sundar - Pasang kembali Monica
sumber
2

Ruby , 57 byte

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

Cobalah online!

Lambda anonim menerima array input a, ukuran chunkn , dan predikat g. Mempertahankan counter citem yang cocok dengan predikat dan mengelompokkan item dengan jumlah potongan yang sudah habis. Sayangnya, nilai awal -1 / n tidak membulatkan ke 0, jadi kita harus menghabiskan beberapa byte untuk memperbaikinya.

Kirill L.
sumber
2

R , 100 byte

function(L,K,P,s=sapply(L,P),y=cut(cumsum(s),seq(0,sum(s),K),,T))for(l in levels(y))cat(L[y==l],"
")

Cobalah online!

dikalahkan dengan mudah oleh digEmAll

Giuseppe
sumber
Saya tidak tahu apakah daftar bernama sebagai output ok (dan jika saya melewatkan beberapa kasus tepi ...): 65 byte
digEmAll
Hmm yah saya akan memposting itu sebagai jawaban terpisah!
Giuseppe
1

Python 2 , 92 byte

lambda a,c,p:reduce(lambda r,v:[r[:-1]+[r[-1]+[v]],r+[[v]]][sum(map(p,r[-1]+[v]))>c],a,[[]])

Cobalah online!

Chas Brown
sumber
1

JavaScript (Node.js) , 90 byte

(s,p,r=[l=[]],n=s+1)=>g=a=>0 in a?g(a,(n=(n||s)-p(v=a.shift()))||r.push(l=[]),l.push(v)):r

Cobalah online!

Diminta sebagai F(2, x => x > 0)([0, 1, 1, 0])

tsh
sumber
1

Mathematica, 82 byte

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}]]

Tidak Disatukan:

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                  *)
  ]

ladalah daftar input; sadalah ukuran chunk;padalah fungsi tanpa nama / anonim / murni / lambda yang mengembalikan operasi benar / salah pada elemen daftar.

Last@Reap[...]mengembalikan daftar daftar setiap elemen yang Sow-n di dalamnya .... Mereka dikelompokkan ke dalam sublists oleh argumen kedua e~Sow~tyang merupakan singkatanSow[e, t] .

Saya harus menginisialisasi penghitung ke -1 untuk menangani ukuran chunk 1, jika tidak saya perlu memeriksa Mod[i, s] (i~Mod~s ) sama dengan 1, yang tidak akan pernah terjadi.

Sisa kode dijelaskan di blok yang tidak ditandai.

LLlAMnYP
sumber