Dividi un elenco in blocchi di dimensioni, ma non contando gli articoli che non hanno predicato


17

Motivazione : a volte alcuni elementi di un elenco non contano ai fini del totale. Ad esempio, contando i passeggeri dell'aereo in file, dove i bambini si siedono sulle ginocchia di un genitore.

Sfida : scrivere un programma per dividere un elenco di elementi in blocchi. Ogni blocco (tranne forse l'ultimo) ha le stesse dimensioni , dove la dimensione è definita come il numero di elementi che passano una funzione predicata.

Regole :

  1. Il tuo programma deve prendere
    • un elenco di elementi
    • una dimensione di pezzo intero positiva
    • una funzione predicato (accetta un elemento e restituisce vero o falso)
  2. È necessario restituire l'elenco di input suddiviso in blocchi
  3. Ogni blocco è un elenco di elementi
  4. Complessivamente, gli articoli devono rimanere nello stesso ordine, senza essere scartati
  5. Il numero di elementi che passano predicato in ciascun blocco (tranne forse l'ultimo) deve corrispondere alla dimensione del blocco di input.
  6. gli articoli che non superano il predicato non devono essere considerati per questa dimensione
  7. Gli elementi che non riescono nel predicato sono
    1. ancora incluso nei blocchi di output
    2. allocato al primo blocco, nel caso in cui un blocco sia "pieno" ma gli elementi successivi sono quelli che falliscono il predicato
      • pertanto il blocco finale potrebbe non essere costituito esclusivamente da elementi che non riescono nel predicato
  8. Il blocco finale può avere dimensioni inferiori a quelle del blocco perché tutti gli articoli sono stati contabilizzati.

Esempi non esaustivi:

L'esempio più semplice è quello di considerare 1s e 0s, dove la funzione predicato è x ==> x > 0. In questo caso, il valore sumdi ciascun blocco deve corrispondere alla dimensione del blocco.

  • articoli :, []dimensione 2:, predicato: x > 0-> o []oppure[[]]
  • articoli :, [0, 0, 0, 0, 0, 0]dimensioni 2:, predicato: x > 0->[[0, 0, 0, 0, 0, 0]]
  • articoli :, [0, 1, 1, 0]dimensioni 2:, predicato: x > 0->[[0, 1, 1, 0]]
  • articoli :, [0, 1, 1, 0, 1, 0, 0]dimensioni 2:, predicato: x > 0->[[0, 1, 1, 0], [1, 0, 0]]
  • articoli :, [0, 1, 0, 0, 1, 0, 1, 1, 0]dimensioni 2:, predicato: x > 0->[[0, 1, 0, 0, 1, 0], [1, 1, 0]]

E finiamo con i passeggeri dell'aereo in cui i bambini siedono sull'esempio del grembo di un genitore . Aper gli adulti, bper i bambini, la fila dell'aereo è 3larga seggi, gli adulti sono sempre elencati prima del loro bambino:

  • articoli :, [A, b, A, b, A, A, A, b, A, b, A, A, b]dimensioni 3:, predicato: x => x == A->[[A, b, A, b, A], [A, A, b, A, b], [A, A, b]]

6
Sembra una buona domanda, ma al momento manca un criterio vincente. Suggerisco di usare code-golf .
Laikoni,

3
Possiamo supporre che le voci dell'elenco siano caratteri singoli? O, diciamo, i numeri?
xnor

il chunking suona interessante, anche se potrebbe essere sostituito da set-partitions .
Jonathan Frech,

@Laikoni ha taggato code-golf
Tom Viner il

1
@Ourous Ho aggiunto "perché tutti gli elementi sono stati contabilizzati", ovvero l'ultimo pezzo non ha la possibilità di "riempirsi", perché è solo la fine degli elementi di input.
Tom Viner,

Risposte:


2

Gelatina , 10 byte

vⱮTm⁵ḊœṖŒṘ

Un programma completo che prende la monadica funzione black-box come primo argomento opzionale, l'elenco come secondo argomento opzionale e la dimensione del blocco come terzo argomento opzionale che stampa una rappresentazione Python dell'elenco di elenchi risultante (per evitare che la schiacciata implicita di Jelly di elenchi contenenti caratteri).

Provalo online! (nota che un elenco di caratteri viene passato a un programma Jelly formattandolo come una stringa tra virgolette di Python)

Come?

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 byte

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

Provalo online!

Sono stato piacevolmente sorpreso di scoprire che questo - praticamente una riaffermazione della domanda - termina con successo e produce un risultato corretto.

Presuppone che il predicato sia presente come predicato 2 sotto questo codice. Emette un elenco di elenchi ("blocchi") o falseper un input vuoto.

Spiegazione:

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 byte (SBCS)

Grazie ad Adám per avermi salvato 1 byte.

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

Provalo online! a scopo di spiegazione lascerò la soluzione a 17 byte.

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

⍺⍺¨⍵applica il predicato all'elenco restituendo un vettore booleano
+\genera un totale parziale
1⌈sostituisce le 0s iniziali con 1s
⌈⍺÷⍨suddivide ciascun elemento per la dimensione del blocco e arrotonda
⍵⊆⍨il vettore originale per partizioni


2
È impressionante! E mi piace il display di output, visuale appropriata per il problema.
Sundar - Ripristina Monica il

Salva un byte convertendolo in programma (tradfn body):w⊆⍨⌈⎕÷⍨1⌈+\⎕¨w←⎕
Adám

5

Pulito , 96 92 byte

Utilizza una funzione denominata f :: a -> Boolconsentita in base al meta consenso.

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

Provalo online!

Espanso (con l'evidenziazione predefinita per mostrare i commenti):

$ 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 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 non è sicuramente la lingua giusta per questa sfida (o per qualsiasi sfida codegolf ovviamente ..)

-21 byte grazie a @OOBalance

Provalo online.

Spiegazione:

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

Formato di input scatola nera:

Presuppone che boolean f(Object i)sia presente una funzione denominata , consentita in base a questa meta risposta .

Ho una classe astratta Testcontenente la funzione predefinita f(i), così come la lambda sopra:

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

Per i casi di test, sovrascrivo questa funzione f. Ad esempio, l'ultimo caso di test si chiama così:

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..)" ehh non lo so, hai eliminato le mie risposte pulite in almeno alcuni casi. Ad ogni modo, aspetto sempre con impazienza le tue risposte.
Οuroso

2
@ Οurous È più che altro un meme che Java non è adatto in alcun modo a codegolf, che immagino si applichi anche a Clean se lo confrontiamo con linguaggi di golf reali come Jelly, 05AB1E, ecc. Mi piace ancora risolvere tutte queste sfide di codegolf in Java però (e presumo anche tu in Clean). E una volta ogni tanto, Java è in grado di battere Python . ;) E una volta ero una delle principali risposte con Java , finché Bash non l'ha rovinato (e R ha continuato a giocare a golf). xD
Kevin Cruijssen,

1
186 byte se si restituisce un elenco di array: bit.ly/2mSjCIc
OOBalance

@OOBalance Grazie! Uso intelligente di Arrays.copyOfRange!
Kevin Cruijssen,

@OOBalance è stato in grado di giocare a golf un po 'di più usando l'ingresso come Elenco e usando .sublist. La tua funzionalità rimane la stessa a parte ciò, ma salva molti byte e rimuove l'importazione. (E ora funziona anche per il test case con caratteri anziché numeri interi.)
Kevin Cruijssen,


3

C (gcc) , 70 66 byte

Uso una struttura per annotare l'inizio di un sotto-elenco, dato che C non è a conoscenza di queste cose.

Grazie a ceilingcat per i suggerimenti.

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

Provalo online!


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]=(![])

Provalo 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' 

3

MATL, 19 byte

HyX$Ysi/Xk1y>+!w7XQ

Basato sull'eccellente risposta APL di jslip .

MATL in realtà non ha funzioni definite dall'utente in quanto tali, ma ha un modo per richiamare l'ambiente in cui è in esecuzione (MATLAB / Octave), quindi questo lo utilizza per la funzione predicato. L'utilizzo sarebbe simile a questo , ma quella funzionalità è disabilitata online per motivi di sicurezza, quindi ecco una versione che utilizza invece una isoddfunzione predicato codificata : Provala su 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

Rubino , 57 byte

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

Provalo online!

Lambda anonimo che accetta array di input a, dimensione del blocco ne predicato g. Mantiene un contatore cdi elementi corrispondenti al predicato e raggruppa gli elementi per il numero di blocchi già utilizzati. Sfortunatamente, il valore iniziale -1 / n non viene arrotondato a 0, quindi è necessario spendere qualche byte per risolverlo.





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

Ungolfed:

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è l'elenco di input; sè la dimensione del pezzo; pè una funzione anonima / anonima / pura / lambda che restituisce vero / falso operando su elementi dell'elenco.

Last@Reap[...]restituisce un elenco di elenchi di ogni elemento che era Sow-n all'interno di .... Sono raggruppati in elenchi secondari dal secondo argomento di e~Sow~tcui è abbreviata Sow[e, t].

Ho dovuto inizializzare i contatori su -1 per gestire una dimensione di blocco di 1, altrimenti avrei dovuto controllare Mod[i, s]( i~Mod~s) uguale a 1, cosa che non potrebbe mai accadere.

Il resto del codice è spiegato nel blocco non golfato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.