Fractionner une liste en morceaux de taille, mais sans compter les éléments ayant échoué au prédicat

17

Motivation : Parfois, certains éléments d'une liste ne comptent pas dans vos totaux. Par exemple, compter les passagers d'un avion en rangées, où les bébés sont assis sur les genoux d'un parent.

Défi : écrire un programme pour diviser une liste d'articles en morceaux. Chaque bloc (sauf éventuellement le dernier) a la même taille , où la taille est définie comme le nombre d'éléments passant une fonction de prédicat.

Règles :

  1. Votre programme doit prendre
    • une liste d'articles
    • une taille de bloc entière positive
    • une fonction de prédicat (prend un élément et renvoie vrai ou faux)
  2. Vous devez renvoyer la liste d'entrée divisée en morceaux
  3. Chaque morceau est une liste d'articles
  4. Globalement, les articles doivent rester dans le même ordre, aucun n'est ignoré
  5. Le nombre d'éléments passant le prédicat dans chaque bloc (sauf éventuellement le dernier) doit correspondre à la taille du bloc d'entrée.
  6. les éléments qui échouent au prédicat ne doivent pas compter dans cette taille
  7. Les éléments qui échouent au prédicat sont
    1. toujours inclus dans les morceaux de sortie
    2. alloué au premier morceau, dans le cas où un morceau est "plein" mais les éléments suivants sont ceux qui échouent au prédicat
      • ainsi le dernier morceau peut ne pas être composé uniquement d'éléments ne respectant pas le prédicat
  8. Le morceau final peut être de taille inférieure à la taille du morceau car tous les articles ont été pris en compte.

Exemples non exhaustifs:

L'exemple le plus simple consiste à considérer 1s et 0s, où se trouve la fonction de prédicat x ==> x > 0. Dans ce cas, le sumde chaque bloc doit correspondre à la taille du bloc.

  • éléments:, []taille 2:, prédicat: x > 0-> []ou[[]]
  • articles:, [0, 0, 0, 0, 0, 0]taille 2:, prédicat: x > 0->[[0, 0, 0, 0, 0, 0]]
  • articles:, [0, 1, 1, 0]taille 2:, prédicat: x > 0->[[0, 1, 1, 0]]
  • articles:, [0, 1, 1, 0, 1, 0, 0]taille 2:, prédicat: x > 0->[[0, 1, 1, 0], [1, 0, 0]]
  • articles:, [0, 1, 0, 0, 1, 0, 1, 1, 0]taille 2:, prédicat: x > 0->[[0, 1, 0, 0, 1, 0], [1, 1, 0]]

Et terminons avec les passagers de l' avion où les bébés sont assis sur les genoux d'un parent . Apour adulte, bpour bébé, la rangée de l'avion est 3large, les adultes sont toujours répertoriés avant leur bébé:

  • articles:, [A, b, A, b, A, A, A, b, A, b, A, A, b]taille 3:, prédicat: x => x == A->[[A, b, A, b, A], [A, A, b, A, b], [A, A, b]]
Tom Viner
la source
6
Cela ressemble à une bonne question, mais il manque actuellement un critère gagnant. Je suggère d'utiliser le code-golf .
Laikoni
3
Pouvons-nous supposer que les éléments de la liste sont des caractères uniques? Ou, disons, des chiffres?
xnor
le découpage semble intéressant, mais pourrait peut-être être remplacé par set-partitions .
Jonathan Frech
@Laikoni a marqué code-golf
Tom Viner
1
@Ourous, j'ai ajouté "parce que tous les éléments ont été pris en compte", c'est-à-dire que le dernier morceau n'a pas la chance d'être "plein", car ce n'est que la fin des éléments d'entrée.
Tom Viner

Réponses:

2

Gelée , 10 octets

vⱮTm⁵ḊœṖŒṘ

Un programme complet prenant la fonction de boîte noire monadique comme premier argument facultatif, la liste comme deuxième argument facultatif et la taille de bloc comme troisième argument facultatif qui imprime une représentation Python de la liste résultante des listes (pour éviter le broyage implicite de Jelly de listes contenant des caractères).

Essayez-le en ligne! (notez qu'une liste de caractères est passée à un programme Jelly en le formatant comme une chaîne entre guillemets Python)

Comment?

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
la source
8

Brachylog , 37 octets

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

Essayez-le en ligne!

J'ai été agréablement surpris de constater que cela - à peu près une reformulation de la question - se termine avec succès et produit une sortie correcte.

Suppose que le prédicat est présent en tant que prédicat 2 sous ce code. Sort une liste de listes ("morceaux"), ou falsepour une entrée vide.

Explication:

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 - Rétablir Monica
la source
7

Apl (Dyalog Unicode) 17 16 octets (SBCS)

Merci à Adám de m'avoir sauvé 1 octet.

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

Essayez-le en ligne! à des fins d'explication, je vais laisser la solution de 17 octets.

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

⍺⍺¨⍵applique le prédicat à la liste renvoyant un vecteur booléen
+\génère un total cumulé
1⌈ remplace le début 0s par 1s
⌈⍺÷⍨divise chaque élément par la taille du bloc et arrondit les
⍵⊆⍨partitions du vecteur d'origine par ce

jslip
la source
2
C'est impressionnant! Et j'aime l'affichage de sortie, visuel approprié pour le problème.
sundar
Enregistrer un octet en convertissant en programme (corps tradfn):w⊆⍨⌈⎕÷⍨1⌈+\⎕¨w←⎕
Adám
5

Nettoyer , 96 92 octets

Utilise une fonction nommée f :: a -> Bool autorisée selon le méta consensus.

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

Essayez-le en ligne!

Développé (avec mise en surbrillance par défaut pour faire apparaître les commentaires):

$ 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
Οurous
la source
4

Java 10, 207 186 159 148 octets

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 n'est certainement pas le bon langage pour ce défi (ou tout défi de codegolf bien sûr ..)

-21 octets grâce à @OOBalance

Essayez-le en ligne.

Explication:

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 d'entrée de la boîte noire:

Suppose qu'une fonction nommée boolean f(Object i)est présente, ce qui est autorisé en fonction de cette méta-réponse .

J'ai une classe abstraite Testcontenant la fonction par défaut f(i), ainsi que la lambda ci-dessus:

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

Pour les cas de test, j'écrase cette fonction f. Par exemple, le dernier cas de test est appelé comme ceci:

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
la source
1
" (or any codegolf-challenge of course..)" ehh je ne sais pas, vous avez battu mes réponses Clean dans au moins quelques cas. Quoi qu'il en soit, j'attends toujours vos réponses avec impatience.
2018 8urous
2
@ Οurous C'est plus un mème que Java ne convient pas au codegolf en aucune façon, ce qui, je suppose, s'applique également à Clean si nous le comparons aux langages de golf réels comme Jelly, 05AB1E, etc. J'aime toujours résoudre tous ces défis de codegolf en Java cependant (et vous en Clean aussi je suppose). Et de temps en temps, Java est capable de battre Python . ;) Et j'étais une fois une réponse de premier plan avec Java , jusqu'à ce que bash le ruine (et R a continué à jouer au golf). xD
Kevin Cruijssen
1
186 octets si vous retournez une liste de tableaux: bit.ly/2mSjCIc
OOBalance
@OOBalance Merci! Utilisation intelligente de Arrays.copyOfRange!
Kevin Cruijssen
@OOBalance a pu jouer un peu plus au golf en utilisant l'entrée comme liste et en utilisant .sublist. Votre fonctionnalité reste la même à part cela, mais elle économise beaucoup d'octets et supprime l'importation. (Et maintenant, cela fonctionne également pour le cas de test avec des caractères au lieu d'entiers.)
Kevin Cruijssen
4

R , 58 octets

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

Essayez-le en ligne!

  • -5 octets grâce à @Giuseppe
digEmAll
la source
1
58 octets
Giuseppe
3

C (gcc) , 70 66 octets

J'utilise une structure pour noter le début d'une sous-liste, car C ne sait pas de telles choses.

Merci à plafondcat pour les suggestions.

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

Essayez-le en ligne!

ErikF
la source
3

Haskell, 72 octets

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

Essayez-le en ligne!

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
la source
3

MATL, 19 octets

HyX$Ysi/Xk1y>+!w7XQ

Basé sur l'excellente réponse APL de jslip .

MATL n'a pas vraiment de fonctions définies par l'utilisateur en tant que telles, mais il a un moyen d'appeler l'environnement sur lequel il s'exécute (MATLAB / Octave), donc cela l'utilise pour la fonction de prédicat. L'utilisation serait quelque chose comme ça , mais cette fonctionnalité est désactivée en ligne pour des raisons de sécurité, alors voici une version qui utilise une isoddfonction de prédicat codée en dur à la place: Essayez-la sur 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 - Rétablir Monica
la source
2

Rubis , 57 octets

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

Essayez-le en ligne!

Lambda anonyme acceptant un tableau d'entrée a, une taille de bloc net un prédicat g. Gère un compteur cd'éléments correspondant au prédicat et regroupe les éléments en fonction du nombre de morceaux déjà utilisés. Malheureusement, la valeur initiale -1 / n n'est pas arrondie à 0, nous devons donc dépenser quelques octets pour le corriger.

Kirill L.
la source
2

R , 100 octets

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],"
")

Essayez-le en ligne!

dominé par digEmAll

Giuseppe
la source
Je ne sais pas si les listes nommées en sortie sont correctes (et si j'ai raté des cas
marginaux
Hmm bien je posterais ça comme une réponse séparée!
Giuseppe
1

JavaScript (Node.js) , 90 octets

(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

Essayez-le en ligne!

Appeler en tant que F(2, x => x > 0)([0, 1, 1, 0])

tsh
la source
1

Mathematica, 82 octets

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

Non golfé:

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

lest la liste d'entrée; sest la taille d'un morceau; pest une fonction sans nom / anonyme / pure / lambda qui renvoie true / false opérant sur les éléments de la liste.

Last@Reap[...]renvoie une liste de listes de chaque élément qui était Sow-n à l'intérieur de .... Ils sont regroupés en sous-listes dont le deuxième argument e~Sow~test l'abréviation de Sow[e, t].

J'ai dû initialiser les compteurs à -1 pour gérer une taille de bloc de 1, sinon je devrais vérifier Mod[i, s]( i~Mod~s) égal à 1, ce qui ne pourrait jamais arriver.

Le reste du code est expliqué dans le bloc non golfé.

LLlAMnYP
la source