Couvrir une ligne d'horizon avec des coups de pinceau

43

À partir d’une liste de hauteur d’horizon entier non négatif, indiquez le nombre de coups de pinceau horizontaux ininterrompus d’une unité de hauteur nécessaires pour la recouvrir.

[1,3,2,1,2,1,5,3,3,4,2], visualisé comme:

      5    
      5  4 
 3    5334 
 32 2 53342
13212153342

nécessite neuf coups de pinceau:

      1    
      2  3 
 4    5555 
 66 7 88888
99999999999

Exemples

[1,3,2,1,2,1,5,3,3,4,2]9

[5,8]8

[1,1,1,1]1

[]0

[0,0]0

[2]2

[2,0,2]4

[10,9,8,9]11

Adam
la source
Pour les utilisateurs intéressés haut rep: D' après ce que par ce .
Adám
2
Donc, tous les coups de pinceau sont horizontaux?
Tsh le
1
@th Bon point. Ajoutée.
Adám
Ce n'était pas codegolf, mais j'avais cette question pour un test de code d'entrevue il y a environ un an.
luizfzs

Réponses:

35

JavaScript (Node.js) , 38 octets

a=>a.map(v=>(n+=v>p&&v-p,p=v),p=n=0)|n

Essayez-le en ligne!

Tout simplement un algorithme glouton qui balaie de gauche à droite, ne trace des lignes que si nécessaire, et le plus longtemps possible.

Merci Arnauld, économisez 2 3 octets

tsh
la source
@ Arnauld belle prise. totalement oublié.
Tsh le
Comment avez-vous réalisé cela?
Adám
@ Adám Rien de magique. La première fois que j'ai lu la question, j'étais confus de savoir comment faire une recherche jusqu'à ce que toutes les lignes soient horizontales. Et puis cette formule vient à mon esprit naturellement ....
tsh
4
la magie semble être un mot approprié pour décrire ce processus.
Adám
1
Bien que ce soit l'origine de l'algorithme maintenant largement utilisé, il est expliqué ici .
Adám
28

05AB1E ,  8 7  5 octets

2 octets sauvés grâce à @Adnan

0š¥þO

Essayez-le en ligne!

Comment?

Ceci utilise l'algorithme qui a été trouvé pour la première fois par @tsh . Si vous aimez cette réponse, assurez-vous de la faire revenir également!

Chaque fois qu'un gratte-ciel est plus bas ou plus haut que le précédent, il peut être peint «gratuitement» en prolongeant simplement les coups de pinceau.

Par exemple, peindre les gratte-ciel et dans la figure ci-dessous ne coûte rien.BC

D'autre part, nous avons besoin de 2 nouveaux coups de pinceau pour peindre le gratte-ciel , peu importe qu'ils soient réutilisés ou non.E

bâtiments

Pour le premier gratte-ciel, nous avons toujours besoin d'autant de coups de pinceau que de sols.

En tournant ça en maths:

S=h0+i=1nmax(hihi1,0)

Si nous ajoutons à la liste, ceci peut être simplifié comme suit:0

S=i=1nmax(hihi1,0)

Commenté

0š¥þO     # expects a list of non-negative integers  e.g. [10, 9, 8, 9]
0š        # prepend 0 to the list                    -->  [0, 10, 9, 8, 9]
  ¥       # compute deltas                           -->  [10, -1, -1, 1]
   þ      # keep only values made of decimal digits
          # (i.e. without a minus sign)              -->  ["10", "1"]
    O     # sum                                      -->  11
Arnauld
la source
Je pense que 0š¥ʒd}Ovous sauve un octet.
M. Xcoder le
@ Don'tbeax-tripledot J'étais en train de modifier ma réponse exactement lorsque j'ai vu votre commentaire;)
Arnauld
4
Belle explication.
Adám
1
Remplacer ʒd}par þdevrait vous faire économiser deux octets.
Adnan le
@ Adam Ah, bien. Merci!
Arnauld
7

Python 3 , 37 octets

lambda a:sum(a)-sum(map(min,a[1:],a))

Essayez-le en ligne!

-5 octets en passant à Python 3, grâce à Sarien


Python 2 , 47 43 42 octets

lambda a:sum(a)-sum(map(min,a[1:],a[:-1]))

Essayez-le en ligne!

Alt:

lambda a:sum(a)-sum(map(min,zip(a[1:],a)))

Essayez-le en ligne!

TFeld
la source
En Python 3, vous pouvez abandonner le [: -1] en économisant 5 octets.
Sarien
@Sarien Merci: D, je ne savais pas que la carte était différente en python 2 et 3
TFeld le
7

Haskell , 32 octets

(0%)
p%(h:t)=max(h-p)0+h%t
p%_=0

Essayez-le en ligne!

Une amélioration de la solution de Lynn qui suit l'élément précédent pau lieu de regarder l'élément suivant. Cela raccourcit le scénario de base et l'appel récursif en échange de la nécessité d'invoquer (0%).

max(h-p)0pourrait être max h p-ppour la même longueur.

Xnor
la source
5

K (oK) , 12 à 7 octets

-5 octets grâce à ngn!

Un port k (oK) de la solution 05AB1E d’Arnauld (et de la solution JavaScript de tsh):

+/0|-':

Essayez-le en ligne!

J , 15 octets

Port AJ de la solution 05AB1E d'Arnauld (et de la solution JavaScript de tsh):

1#.0>./2-~/\0,]

Essayez-le en ligne!

Ma solution naïve:

J , 27 octets

1#.2(1 0-:])\0,@|:@,~1$~"0]

Essayez-le en ligne!

Galen Ivanov
la source
2
oK: chaque prior ( ':) utilise un élément d'identité implicite ( 0pour -) avant la liste, il 0,est donc inutile. vous pouvez omettre { x}d'en faire une composition:+/0|-':
ngn
@ngn Merci! Apparemment, j'ai oublié ceci:Some primitive verbs result in a different special-cased initial value: +, *, - and & are provided with 0, 1, 0 or the first element of the sequence, respectively
Galen Ivanov
5

Haskell , 34 32 octets

2 octets coupés par Lynn

g x=sum$max 0<$>zipWith(-)x(0:x)

Essayez-le en ligne!

Donc pour commencer nous avons zipWith(-). Cela prend deux listes et produit une nouvelle liste de leurs différences par paires. Nous le combinons ensuite avec xet (0:x). (0:)est une fonction qui ajoute zéro au début d'une liste et en la combinant avec zipWith(-)nous obtenons les différences entre les éléments consécutifs de cette liste avec un zéro au début. Ensuite, nous mettons tous les négatifs à zéro avec (max 0<$>). Cela crée une nouvelle liste où chaque élément est le nombre de nouveaux traits qui doivent être démarrés à chaque tour. Pour obtenir le total, nous les additionnons simplement avec sum.

Assistant de blé
la source
2
g x=sum$max 0<$>zipWith(-)x(0:x)est 32 octets :)
Lynn
Tel sum.zipWith((max 0.).(-))<*>(0:)
quel
@ Lynn Votre deuxième va avoir besoin de parenthèses supplémentaires car il .a une priorité plus élevée que <*>.
Wheat Wizard
3

Japt , 8 octets

-2 octets de @Shaggy

mîT Õ¸¸è

Explication

mîT Õ¸¸è      Full program. Implicit input U
                e.g. U = [2,0,2]
mîT             Map each item X and repeat T(0) X times
                     U = ["00","","00"]
    Õ           Transpose rows with columns
                     U = ["0 0","0 0"]
     ¸¸         Join using space and then split in space
                     U = ["0","0","0","0"]
        è       Return the count of the truthy values

Essayez-le en ligne!

Luis Felipe De Jesus Munoz
la source
8 octets:mîT Õ¸¸è
Shaggy le
1
Au fait, bon usage du A.y()rembourrage.
Shaggy
3

MATL , 8 octets

0whd3Y%s

Essayez-le en ligne!

Joli algorithme de @ Arnauld. Sauvegardé d'un octet (merci @LuisMendo) en utilisant uint64plutôt que de sélectionner )des entrées positives.

Sanchises
la source
3

Gelée , 5 octets

Un port de ma réponse 05AB1E , qui est semblable à @tsh JS answer .

ŻI0»S

Essayez-le en ligne!

Commenté

ŻI0»S    - main link, expecting a list of non-negative integers  e.g. [10, 9, 8, 9]
Ż        - prepend 0                                             -->  [0, 10, 9, 8, 9]
 I       - compute the deltas                                    -->  [10, -1, -1, 1]
  0»     - compute max(0, v) for each term v                     -->  [10, 0, 0, 1]
    S    - sum                                                   -->  11
Arnauld
la source
3

Japt , 7 à 6 octets

änT fq

L'essayer

1 octet enregistré grâce à Oliver.

änT xwT    :Implicit input of integer array
än         :Consecutive differences / Deltas
  T        :  After first prepending 0
    f      :Filter elements by
     q     :  Square root (The square root of a negative being NaN)
           :Implicitly reduce by addition and output
Hirsute
la source
1
6 octets
Oliver
Nice, @Oliver; n'aurait pas pensé à cela.
Shaggy
2

Retina 0.8.2 , 21 octets

\d+
$*
(1+)(?=,\1)

1

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

\d+
$*

Convertir en unaire.

(1+)(?=,\1)

Supprimez tous les chevauchements avec la tour suivante, qui n'ont pas besoin d'un nouveau trait.

1

Comptez les coups restants.

Neil
la source
2

Common Lisp, 88 87 octets

(lambda(s)(let((o 0))(dolist(c s)(incf o(max 0 c))(mapl(lambda(y)(decf(car y)c))s))o))

non minifié

(lambda (skyline)
  (let ((output 0))
    (dolist (current-skyscraper-height skyline)
      (incf output (max 0 current-skyscraper-height))
      (mapl (lambda (skyscraper)
              (decf (car skyscraper) current-skyscraper-height))
            skyline))
    output)))

Essaye-le

Quand une tour est peinte, il faut un nombre de coups de pinceau égal à sa hauteur. Ces coups de pinceau se traduisent par tous les suivants, ce qui est indiqué ici en soustrayant la hauteur de la tour actuelle de toutes les autres tours (et elle-même, mais cela n'a pas d'importance). Si une tour suivante est plus courte, elle sera poussée à un nombre négatif et ce nombre négatif sera ensuite soustrait des tours suivantes (indiquant les coups de pinceau qui n'ont pas pu être traduits d'une tour précédente). En fait, il ne fait que soustraire le nombre de toutes les hauteurs de tour, y compris les précédentes, mais cela n'a pas d'importance, car nous ne regardons plus les précédentes.

Charlim
la source
Bienvenue chez PPCG. Pourriez-vous éventuellement fournir un lien vers un environnement de test en ligne pour faciliter la vérification?
Jonathan Frech
Oui absolument. rextester.com/TKBU14782 La réponse sera mise à jour sous peu
Charlim
Bien joué. +1 pour un premier poste de travail agréable. Amusez-vous à jouer au golf.
Jonathan Frech
1

05AB1E , 13 à 10 octets

Z>Lε@γPO}O

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

Z            # Get the maximum of the (implicit) input-list
 >           # Increase it by 1 (if the list only contains 0s)
  L          # Create a list in the range [1, max]
   ε         # Map each value to:
    @        #  Check if this value is >= for each value in the (implicit) input
     γ       #  Split into chunks of adjacent equal digits
      P      #  Take the product of each inner list
       O     #  Take the sum
        }O   # And after the map: take the sum (which is output implicitly)
Kevin Cruijssen
la source
1

C # (compilateur interactif Visual C #) avec indicateur /u:System.Math, 47 octets

n=>n.Select((a,i)=>i<1?a:Max(a-n[i-1],0)).Sum()

Essayez-le en ligne!

Ancienne version, avec drapeau /u:System.Math, 63 octets

n=>n.Aggregate((0,0),(a,b)=>(a.Item1+Max(0,b-a.Item2),b)).Item1

J'ai l'impression que cette solution est plus élégante que la première. Il parcourt le tableau avec un tuple à deux valeurs comme valeur de départ, en sélectionnant des valeurs, et stocke la valeur qui le précède dans la seconde partie du tuple.

Essayez-le en ligne!

Incarnation de l'ignorance
la source
1

Pyth, 8 octets

s>#0.++0

Encore une autre réponse merveilleuse de @ tsh . Prend la somme ( s) des valeurs positives ( >#0) des deltas (. +) De l'entrée avec 0 en préfixe ( +0QQ inféré).

Essayez-le en ligne ici ou vérifiez tous les cas de test en même temps ici .

Méthode de jonction de chaînes, 10 octets

C’est la solution que j’ai écrite avant de parcourir les autres réponses.

lcj.t+d*LN

Suite de tests.

lcj.t+d*LNQ   Implicit: Q=eval(input()), b=<newline>, N=<quote mark>
              Trailing Q inferred
        L Q   Map each element of Q...
       * N    ... to N repeated that many times
     +b       Prepend a newline
   .t         Transpose, padding with spaces
  j           Join on newlines
 c            Split on whitespace
l             Take the length, implicit print
Sok
la source
1

Clojure, 50 octets

#((reduce(fn[[s n]i][(+(max(- i n)0)s)i])[0 0]%)0)

Essayez-le en ligne! (Pourquoi cela n'imprime-t-il rien?)

#( ; begin anonymous function
    (reduce
        (fn [[s n] i] ; internal anonymous reducing function, destructures accumulator argument into a sum and the previous item
            [(+ (max (- i n) 0) s ; the sum part of the accumulator becomes the previous sum plus the larger of zero and the difference between the current number and the last one, which is how many new strokes need to be started at this point
            i]) ; ...and the previous item part becomes the current item
        [0 0] ; the initial value of the accumulator gives no strokes yet, and nothing for them to cover yet
        %) ; reduce over the argument to the function
    0) ; and get the sum element of the last value of the accumulator.
Essayé de créer un compte
la source
Bienvenue chez PPCG! Je ne connais rien à Clojure, mais une recherche rapide montre que vous devez évaluer la boucle paresseuse. Essayez-le en ligne! (Astuce: vous pouvez utiliser le bouton Lien pour formater automatiquement votre réponse). J'espère que vous restez et amusez-vous!
Jo King le
1

Java (JDK) , 57 octets

a->{int s=0,p=0;for(int x:a)s-=(x>p?p:x)-(p=x);return s;}

Essayez-le en ligne!

Un autre port de la réponse Javascript de tsh . Donc, assurez-vous de les avoir votés.

Notez que j'ai utilisé la soustraction au lieu de l'addition, car cela me permettait d'écrire en (p=x)tant qu'opérande droit dans la même instruction.

Olivier Grégoire
la source
0

MATL , 15 14 13 octets

ts:<~"@Y'x]vs

L'entrée est un vecteur de colonne, utilisant ;comme séparateur.

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

t       % Implicit input: column vector. Duplicate
s       % Sum
:       % Range from 1 to that. Gives a row vector
<~      % Greater or equal? Element-wise with broadcast
"       % For each column
  @     %   Push current columnn
  Y'    %   Run-length encoding. Gives vector of values (0, 1) and vector of lengths
  x     %   Delete vector of lengths
]       % End
v       % Vertically concatenate. May give an empty array
s       % Sum. Implicit display
Luis Mendo
la source
0

Perl 5, 21 octets

$\+=$_>$'&&$_-$';//}{

TIO

Comment

  • -p+ }{+ $\astuce
  • //correspond à une chaîne vide de sorte que pour la ligne suivante, postmatch $'contienne la ligne précédente
  • $\+=$_>$'&&$_-$'accumuler la différence entre la ligne courante et précédente si le courant est supérieur au précédent, (pourrait également être écrit $\+=$_-$' if$_>$', mais Perl n'analyse pas de $\+=$_-$'if$_>$'la même façon)
Nahuel Fouilleul
la source