# Upward and onward to greater glory!

May this challenge serve as (another) tribute to Stan Lee, who passed away aged 95.

Stan Lee has left us an invaluable legacy and a peculiar catch word: Excelsior. So here's a small challenge based on what he said it was its meaning:

Finally, what does “Excelsior” mean? “Upward and onward to greater glory!” That’s what I wish you whenever I finish tweeting! Excelsior!

### Challenge

Given a series of non-negative integers, output a line with Excelsior! every time an integer is greater than the previous one.

### Rules

• Input will be an array of non-negative integers.
• Output will consist of lines with the word Excelsior (case does matter) followed by as many ! as the length of the current run of increasingly greater numbers. You can also return an array of strings.
• Input and output formats are flexible according to the site rules, so feel free to adapt them to your language formats. You can also add spaces at the end of the lines, or even extra new lines after or before the text if you need.

### Examples

Input             Output
-----------------------------------
[3,2,1,0,5]       Excelsior!      // Excelsior because 5 > 0

[1,2,3,4,5]       Excelsior!      // Excelsior because 2 > 1
Excelsior!!     // Excelsior because 3 > 2 (run length: 2)
Excelsior!!!    // Excelsior because 4 > 3 (run length: 3)
Excelsior!!!!   // Excelsior because 5 > 4 (run length: 4)

[]                <Nothing>

[42]              <Nothing>

[1,2,1,3,4,1,5]   Excelsior!      // Excelsior because 2 > 1
Excelsior!      // Excelsior because 3 > 1
Excelsior!!     // Excelsior because 4 > 3 (run length: 2)
Excelsior!      // Excelsior because 5 > 1

[3,3,3,3,4,3]     Excelsior!      // Excelsior because 4 > 3


This is , so may the shortest code for each language win!

• ouflak assumes integers are 1 digit long, is that ok – ASCII-only Nov 14 '18 at 10:48
• @ASCII-only not really. I don't know if LUA has a limitation with that, but if that's not the case ouflak should parse integers of any length. – Charlie Nov 14 '18 at 11:04
• @Charlie I don't know Lua, but although it's verbose, it is possible to take for example a space-delimited input and split like this. – Kevin Cruijssen Nov 14 '18 at 13:59
• I'm looking at it. The trick is to be able to handle both scenarios. – ouflak Nov 14 '18 at 14:17
• FWIW languages like C or Javascript will only handle integers within its precision (9/16 digits) anyway. – user202729 Nov 14 '18 at 16:20

# JavaScript (ES6), 58 54 bytes

a=>a.map(c=>a<(a=c)?Excelsior${s+='!'} :s='').join  Try it online! ### Commented a => // a[] = input array, also used to store the previous value a.map(c => // for each value c in a[]: a < // compare the previous value (a = c) // with the current one; update a to c // this test is always falsy on the 1st iteration ? // if a is less than c: Excelsior${s += '!'}\n //     add a '!' to s and yield 'Excelsior' + s + linefeed
:                          //   else:
s = ''                   //     reset s to an empty string and yield an empty string
).join                     // end of map(); join everything


### Why re-using a[ ] to store the previous value is safe

There are three possible cases:

• If $$\a[\text{ }]\$$ is empty, the callback function of .map() is not invoked at all and we just get an empty array, yielding an empty string.
• If $$\a[\text{ }]\$$ contains exactly one element $$\x\$$, it is coerced to that element during the first (and unique) test a < (a = c). So, we're testing $$\x < x\$$, which is falsy. We get an array containing an empty string, yielding again an empty string.
• If $$\a[\text{ }]\$$ contains several elements, it is coerced to NaN during the first test a < (a = c). Therefore, the result is falsy and what's executed is the initialization of $$\s\$$ to an empty string -- which is what we want. The first meaningful comparison occurs at the 2nd iteration.

# Python 2, 84838170 68 bytes

a=n=''
for b in input():
n+='!';n*=a<b;a=b
if n:print'Excelsior'+n


Try it online!

-2 bytes, thanks to ASCII-only

• 68? – ASCII-only Nov 14 '18 at 9:31
• @ASCII-only Thanks :) – TFeld Nov 14 '18 at 9:34
• functions are too long :( – ASCII-only Nov 14 '18 at 9:46
• well, recursive approaches at least – ASCII-only Nov 14 '18 at 9:48
• same with zip – ASCII-only Nov 14 '18 at 9:50

# 05AB1E, 2624 23 bytes

ü‹γvyOE.•1Š¥èò²•™N'!×«,


-2 bytes thanks to @Kroppeb.

Explanation:

ü                        # Loop over the (implicit) input as pairs
‹                       #  And check for each pair [a,b] if a<b is truthy
#   i.e. [1,2,1,3,4,1,5,7,20,25,3,17]
#   → [1,0,1,1,0,1,1,1,1,0,1]
γ                      # Split it into chunks of equal elements
#  i.e. [1,0,1,1,0,1,1,1,1,0,1]
#   → [[1],[0],[1,1],[0],[1,1,1,1],[0],[1]]
vy                    # Foreach y over them
O                   #  Take the sum of that inner list
#   i.e. [1,1,1,1] → 4
#   i.e. [0] → 0
E                  #  Inner loop N in the range [1, length]:
.•1Š¥èò²•         #   Push string "excelsior"
™        #   Titlecase it: "Excelsior"
N'!×«  '#   Append N amount of "!"
#    i.e. N=3 → "Excelsior!!!"
,  #   Output with a trailing newline


See this 05AB1E tip of mine (section How to compress strings not part of the dictionary?) to understand why .•1Š¥èò²• is "excelsior".

• I don't really know 05AB1E but can't you exchange the 0Kg with O? – Kroppeb Nov 14 '18 at 10:39
• @Kroppeb Ah, completely missed that, but yes, I indeed can. Thanks! :) – Kevin Cruijssen Nov 14 '18 at 10:42

# Perl 6, 60 58 57 bytes

-1 byte thanks to nwellnhof

{"Excelsior"X~("!"Xx grep +*,[\[&(-+^*×*)]] .skip Z>$_)}  Try it online! Anonymous code block that returns a list of Excelsiors! # Java-8118 113 Bytes n->{String e="";for(int i=0;i<n.length-1;)System.out.print(""==(n[i+1]>n[i++]?e+="!":(e=""))?e:"Excelsior"+e+"\n");}  Easy to read : private static void lee(int num[]) { String exclamation = ""; for (int i = 0; i < num.length - 1;) { exclamation = num[i + 1] > num[i++] ? exclamation += "!" : ""; System.out.print("".equals(exclamation) ? "" : "Excelsior" + exclamation + "\n"); } }  • Here some golfs to save 10 bytes: n->{var e="";for(int i=0;i<n.length-1;System.out.print(""==e?e:"Excelsior"+e+"\n"))e=n[i++]<n[i]?e+="!":"";}. Try it online (108 bytes). (Java 10+) – Kevin Cruijssen Nov 14 '18 at 10:38 • @KevinCruijssen Thanks! – ΔȺȾΔ Nov 14 '18 at 11:48 • n->{for(int e=0,i=0;i<n.length-1;)if(n[i++]<n[i])System.out.println("Excelsior"+"!".repeat(e++));else e=0;} (107 bytes) – Olivier Grégoire Nov 14 '18 at 14:34 • Fixing my issue: ++e instead of e++ so that there is at least one ! to be printed. – Olivier Grégoire Nov 15 '18 at 10:39 • @KevinCruijssen Small typo in your golf to make you gain one byte: e=...?e+"!": instead of e=...?e+="!":. – Olivier Grégoire Nov 20 '18 at 14:57 # R, 86 bytes Half of this answer is @Giuseppe's. RIP Stan Lee. function(a)for(i in diff(a))"if"(i>0,cat("Excelsior",rep("!",F<-F+1)," ",sep=""),F<-0)  Try it online! # 05AB1E, 20 19 bytes ü‹0¡€ƶ˜ε'!×”¸Îsiorÿ  Try it online! Explanation ü‹ # pair-wise comparison, less-than 0¡ # split at zeroes €ƶ # lift each, multiplying by its 1-based index ˜ # flatten ε # apply to each '!× # repeat "!" that many times ÿ # and interpolate it at the end of ”¸Îsior # the compressed word "Excel" followed by the string "sior"  # C (gcc/clang), 10699 97 bytes f(a,n)int*a;{int r=0,s[n];for(memset(s,33,n);n-->1;)r*=*a<*++a&&printf("Excelsior%.*s\n",++r,s);}  Thanks to gastropner for golfing 2 bytes. Try it online here. Ungolfed: f(a, n) // function taking a pointer to the first integer and the length of the array int *a; { // a is of type pointer to int, n is of type int int r = 0, // length of the current run i = 0, // loop variable s[n]; // buffer for exclamation marks; we will never need more than n-1 of those (we are declaring an array of int, but really we will treat it as an array of char) for(memset(s, 33, n); // fill the buffer with n exclamation marks (ASCII code 33) n -- > 1; ) // loop over the array r *= *a < *(++ a) // if the current element is less than the next: && printf("Excelsior%.*s\n", // print (on their own line) "Excelsior", followed by ... ++ r, // ... r (incremented) of the ... s) // ... n exclamation marks in the buffer s ; // else r is reset to 0 }  • I started making a solution, but ended up so close to yours that posting mine as a separate answer felt a bit silly. Still, the few differences there are can save you a few bytes. – gastropner Nov 15 '18 at 21:27 • @gastropner Thanks for sharing your version. I have incorporated your improvements and golfed it further to 99 bytes. If only we didn't need to handle the empty array – otherwise it would be 97 bytes, using your style of loop. – O.O.Balance Nov 16 '18 at 14:08 # Japt -R, 25 22 bytes ò¨ ËÅ£Ex­lÐâú'!Y+A c  Try it 3 bytes saved thanks to Kamil ò¨ :Partition at items that are greater than or equal to the previous item Ë :Map Å : Slice off the first element £ : Map each element at 0-based index Y Ex­lÐâ : Compressed string "Excelsior" ú'! : Right pad with exclamation marks Y+A : To length Y+10 c :Flatten :Implicitly join with newlines & output  • Another 25 bytes – Luis felipe De jesus Munoz Nov 14 '18 at 12:31 • The -R flag isn't actually necessary, the challenge says you can output an array of strings. – Kamil Drakari Nov 14 '18 at 15:33 • Nice one, thanks, @KamilDrakari. I tried a solution using slice on my first pass but dismissed it when it worked out too long. Coming back to it now, with your prompting, I guess I should have stuck with it 'cause I got it down to 22 too. – Shaggy Nov 16 '18 at 16:29 # Common Lisp, 111 bytes (setq i 0)(loop for(a b)on(read)do(incf i(if(and b(> b a))1(- i)))(format(> i 0)"Excelsior~v@{~a~:*~}~%"i #\!))  Try it online! # Java 8, 106 bytes n->{String s="",z=s;for(int i=0;i<n.length-1;)z+=n[i++]<n[i]?"Excelsior"+(s+="!")+"\n":(s="")+s;return z;}  Try it online! (those reassignments of s...yikes) • You can golf two more bytes by replacing (s="")+s => (s="") – O.O.Balance Nov 15 '18 at 10:38 • n->{String s="",z=s;for(int i=0;i<n.length-1;)z+=n[i++]>=n[i]?s="":"Excelsior"+(s+="!")+"\n";return z;} (103 bytes) Move the s="" to spare bytes. – Olivier Grégoire Nov 15 '18 at 10:41 # Stax, 17 bytes Θx7├╖&σ '@7g┼┘Ñ«═  Run and debug it # R, 111 bytes function(a,r=rle(sign(diff(a))),v=r$l[r$v>0])write(paste0(rep("Excelsior",sum(v)),strrep("!",sequence(v))),1,1)  Try it online! A far better R tribute can be found here -- I was too fixated on sequence and rle. • This doesn't give some blank lines, but 86 bytes? – J.Doe Nov 14 '18 at 19:26 • @J.Doe dang, that's way better. I'd post that myself if I were you. – Giuseppe Nov 14 '18 at 20:48 # Jelly, 16 bytes <Ɲṣ0ÄẎ”!ẋ“Ø6ḥ»;Ɱ  A monadic Link yielding a list of lists of characters. Try it online! (footer joins with newlines) ### How? <Ɲṣ0ÄẎ”!ẋ“Ø6ḥ»;Ɱ - Link: list of integers e.g. [1,1,4,2,1,1,3,4] Ɲ - for each pair of integers: [1,1] [1,4] [4,2] [2,1] [1,1] [1,3] [3,4] < - less than? [ 0, 1, 0, 0, 0, 1, 1] ṣ0 - split at zeros [[], [1], [], [], [1, 1]] Ä - cumulative sums [[], [1], [], [], [1, 2]] Ẏ - tighten [1,1,2] ”! - literal '!' character '!' ẋ - repeat (vectorises) [['!'],['!'],['!','!']] “Ø6ḥ» - dictionary lookup ['E','x','c','e','l','s','i','o','r'] Ɱ - map with: ; - concatenate [['E','x','c','e','l','s','i','o','r','!'],['E','x','c','e','l','s','i','o','r','!'],['E','x','c','e','l','s','i','o','r','!','!']]  # Perl 5-n, 41 bytes $_>$l&&$l?say$c.='!':($c=Excelsior);$l=$_


Try it online!

Takes its input on separate lines.

# Japt, 22 bytes

ò¨ ®£Ex­lÐâ+'!pYÃÅÃc


Try it online!

Explanation, with simplified example:

ò¨                       :Split whenever the sequence does not increase
e.g. [2,1,1,3] -> [[2],[1],[1,3]]
®               Ã     :For each sub-array:
£            Ã       :  For each item in that sub-array:
Ex­lÐâ             :    Compressed "Excelsior"
+            :    Concat with
'!pY        :    a number of "!" equal to the index
e.g. [1,3] -> ["Excelsior","Excelsior!"]
Å      :  Remove the first item of each sub-array
e.g. [[Excelsior],[Excelsior],[Excelsior,Excelsior!]]->[[],[],[Excelsior!]]
c    :Flatten
e.g. [[],[],[Excelsior!]] -> [Excelsior!]


# Powershell, 69 bytes

$args|%{if($o-ne$e-and$_-gt$o){'Excelsior'+'!'*++$c}else{$c=0}$o=$_}  Less golfed test script: $f = {

$args|%{ if($old-ne$empty-and$_-gt$old){ 'Excelsior'+'!'*++$c
}else{
$c=0 }$old=$_ } } @( ,( (3,2,1,0,5), 'Excelsior!') # Excelsior because 5 > 0 ,( (1,2,3,4,5), 'Excelsior!', # Excelsior because 2 > 1 'Excelsior!!', # Excelsior because 3 > 2 (run length: 2) 'Excelsior!!!', # Excelsior because 4 > 3 (run length: 3) 'Excelsior!!!!') # Excelsior because 5 > 4 (run length: 4) ,($null,         '')                # <Nothing>

,( (42),          '')                # <Nothing>

,( (1,2,1,3,4,1,5), 'Excelsior!',      # Excelsior because 2 > 1
'Excelsior!',      # Excelsior because 3 > 1
'Excelsior!!',     # Excelsior because 4 > 3 (run length: 2)
'Excelsior!')      # Excelsior because 5 > 1

,( (3,3,3,3,4,3),   'Excelsior!')      # Excelsior because 4 > 3
) | % {
$a,$expected = $_$result = &$f @a "$result"-eq"$expected"$result
}


Output:

True
Excelsior!
True
Excelsior!
Excelsior!!
Excelsior!!!
Excelsior!!!!
True
True
True
Excelsior!
Excelsior!
Excelsior!!
Excelsior!
True
Excelsior!

• There it is, I was trying to get a lag pointer to work but couldn't think of how. – Veskah Nov 18 '18 at 0:38

param($n)for(;++$i-lt$n.count){if($n[$i]-gt$n[$i-1]){"Excelsior"+"!"*++$c}else{$c=0}}  Try it online! There's probably a restructuring hiding in there, most likely in the if-else, but overall pretty alright. Uses the ol' "Un-instantiated variable defaults to 0" trick for both making the index and the !. # Retina, 55 bytes \d+ * L$rv(_*,(?<!(?(1)\1|\2,)))+(_+)\b
Excelsior$#1*!  Try it online! Link includes test cases. Explanation: \d+ *  Convert to unary. rv(_*,(?<!(?(1)\1|\2,)))+(_+)\b  Process overlapping matches from right to left (although the matches are then listed from left to right). This means that we can match every number in a run, and the match extends to the start of the run. Each match is further constrained that each additional matched number must be less than the previously matched additional number, or the first number if no additional numbers have been matched yet. L$...
Excelsior$#1*!  For each match, output Excelsior with the number of additional numbers in the run as desired. # Pyth, 32 bytes j+L"Excelsior"*L\!fT.u*hN<0Y.+Q0  Try it online here, or verify all the test cases at once here. j+L"Excelsior"*L\!fT.u*hN<0Y.+Q0 Implicit: Q=eval(input()) .+Q Get forward difference between consecutive elements of Q .u 0 Reduce the above, returning all steps, with current value N starting at 0, next element as Y, using: hN N+1 * Multiplied by <0Y 1 if 0<Y, 0 otherwise fT Filter to remove 0s *L\! Repeat "!" each element number of times +L"Excelsior" Prepend "Excelsior" to each j Join on newlines, implicit print  # Jelly, 18 bytes <Ɲ‘×¥\ḟ0”!ẋ“Ø6ḥ»;Ɱ  Try it online! Output prettified over TIO. # Lua, 888783829695 113 bytes Thanks @Kevin Cruijssen for update adhering to spirit of original question. s=io.read()n=9 e="Excelsior!"f=e for c in s.gmatch(s,"%S+")do if n<c+0then print(e)e=e..'!'else e=f end n=c+0 end  Try it online! • Sorry but you need to print the exclamation mark according to the rules (one exclamation mark per length of the current run of increasingly greater numbers). – Charlie Nov 14 '18 at 9:49 • No problem. Think I've done as much as I can do here unless someone else sees something... – ouflak Nov 14 '18 at 9:56 • I don't know Lua too well, but here is a fix for your code so it runs all test cases correctly Currently you just print an "!" more every time a number is higher than the previous, but you don't reset it back to 1 when that isn't the case. More can probably be golfed, but since I've never golfed in Lua I focused on fixing it with only minor golfs. PS: Not sure if assuming the input are always single digits is correct.. – Kevin Cruijssen Nov 14 '18 at 13:43 • Since @Charlie mentioned in a comment below the challenge description that it should be possible to take multi-digits numbers as input, here a possible fix by taking a space-delimited input and split on it. – Kevin Cruijssen Nov 14 '18 at 14:01 • I decided that Kevin Cruijssen modifications are more inline with the OP's expectation. Thanks! – ouflak Nov 14 '18 at 15:02 # C++ 14 (g++), 123 118 bytes [](auto a){for(int n=0,i=0;++i<a.size();)a[i]>a[i-1]?puts(&("Excelsior"+std::string(++n,33))[0]):n=0;}  Fortunately std::string has a constructor that repeats a char. Try it online here. Thanks to gastropner for saving 5 bytes. Ungolfed: [] (auto a) { // void lambda taking a std::array of integer for(int n = 0, // length of the current run i = 0; // loop variable ++ i < a.size(); ) // start with the second element and loop to the last a[i] > a[i - 1] // if the current element is greater than the previous ... ? puts( // ... print a new line: &("Excelsior" + // "Excelsior, followed by ... std::string(++ n, 33)) // ... the appropriate number of exclamation marks (33 is ASCII code for '!'); increment the run length [0]) // puts() takes a C string : n = 0; // else reset run length }  # C# (.NET Core), 115107 105 bytes a=>{var b="";for(int i=0;++i<a.Length;)if(a[i]>a[i-1])Console.WriteLine("Excelsior"+(b+="!"));else b="";}  Try it online! -8 bytes: changed b to a string holding "!"s from an int counter -2 bytes: set b+="!" as an inline function (thanks to Zac Faragher) Uses an Action delegate to pull in the input and not require a return. Ungolfed: a => { var b = ""; // initialize the '!' string (b) for(int i = 0; ++i < a.Length;) // from index 1 until the end of a if(a[i] > a[i - 1]) // if the current index is greater than the previous index Console.WriteLine("Excelsior" + // on a new line, print "Excelsior" (b += "!")); // add a "!" to b, and print the string else // if the current index is not greater than the previous index b = ""; // reset b }  • you can save 2 bytes by making the b+="!" inline with the Excelsior if(a[i]>a[i-1])Console.WriteLine("Excelsior"+(b+="!")); Try it online! – Zac Faragher Nov 16 '18 at 3:48 # PHP, 117 109 bytes <?php do{$i=next($argv);if($p!==null&&$p<$i){$e.='!';echo " Excelsior$e";}else$e='';$p=$i;}while($i!==false);


Try it online!

# J, 50 bytes

'Excelsior',"1'!'#"0~[:;@(([:<+/\);._1)0,2</\ ::0]


Try it online!

## ungolfed

'Excelsior' ,"1 '!' #"0~ [: ;@(([: < +/\);._1) 0 , 2 </\ ::0 ]


Java, 113 bytes

String i="";for(int a=0;a<s.length-1;a++){if(s[a+1]>s[a]){i+="!";System.out.println("Excelsior"+i);}else{i="";}}


VBA, 114 bytes

For i=0 To UBound(a)-LBound(a)-1 If a(i+1)>a(i)Then s=s&"!" Debug.Print("Excelsior"&s&"") Else s="" End If Next i

• Unfortunately, this is not a valid solution as it relies on having an explicitly defined variable, a. That said, if you define the function as a subroutine that takes the input as a variant of expected type array, then you can turn your approach into a valid solution. A Golfed version of that approach would look like sub f(x) For i=0To UBound(x)-1 If x(i+1)>x(i)Then s=s+"!":Debug.?"Excelsior"s:Else s="" Next End Sub, where the breaks between code block represent new lines – Taylor Scott Feb 13 '19 at 22:18

## Python 3, 87 bytes

c='!'
for i in range(1,len(n)):
if n[i]>n[i-1]:print('Excelsior'+c);c+='!'
else:c='!'


Or 97 with the following:

c='!';n=input()
for i in range(1,len(n)):
if n[i]>n[i-1]:print('Excelsior'+c);c+='!'
else:c='!'


This assumes inputs will be in the format:

32105
12345
<null input>
1
1213415
333343

• Your first program is invalid as it takes input through a predefined variable. The second is invalud as it can't distinguish between numbers with multiple digits. Why not use Python 2 or turn it into a function instead? – Jo King Nov 16 '18 at 21:22

# Japt, 25 bytes

ä< ®?Ex­lÐâ+'!p°T:T=0
f


Try it online!