Munge my password

17

3

Common words should still be avoided to be used as passwords. This challenge is about coding a very simple program that munges a given password (Modify Until Not Guessed Easily).

Input

A word, which is a string written in the alphabet abcdefghijklmnopqrstuvwxyz. It does not matter if the letters are lowercase or uppercase.

Munging

  1. Change any repeated sequence of a same letter to itself preceded by the number of times the letter was repeated (LLLL with 4L)
  2. Change the first a with @
  3. Change the first b with 8
  4. Change the first c with (
  5. Change the first d with 6
  6. Change the first e with 3
  7. Change the first f with #
  8. Change the first g with 9
  9. Change the first h with #
  10. Change the first i with 1
  11. Change the second i with !
  12. Change the first k with <
  13. Change the first l with 1
  14. Change the second l with i
  15. Change the first o with 0
  16. Change the first q with 9
  17. Change the first s with 5
  18. Change the second s with $
  19. Change the first t with +
  20. Change the first v with >
  21. Change the second v with <
  22. Change the first w with uu
  23. Change the second w with 2u
  24. Change the first x with %
  25. Change the first y with ?

Rule 1 must be applied the needed number of times until it is not possible to apply it more. After that the rest of the rules are applied.

Output The munged word

Examples

  • codegolf --> (0639o1#
  • programming --> pr09r@2m1ng
  • puzzles --> pu2z135
  • passwords --> p@25uu0r6$
  • wwww --> 4uu
  • aaaaaaaaaaa --> 11a
  • lllolllolll --> 3103io3l
  • jjjmjjjj --> 3jm4j

This is , so please make your program as short as possible!

Nothing in this post should be used as password ideas or as any part of password practices.

mdahmoune

Posted 2017-10-19T12:47:44.200

Reputation: 2 605

18The very fact that programs like this are possible means that the attacker could write them and munge the password (and try the various munges) just as easily (even easier because they often have access to better hardware). So just for safety's sake I will say: nothing in this post should be used as password ideas or as any part of password practices. – NH. – 2017-10-19T16:41:37.017

1I recommend making that disclaimer bold and duplicating it at the top. You can never be too careful... – wizzwizz4 – 2017-10-21T13:57:23.617

Answers

11

Java 8, 237 321 319 280 247 241 240 237 bytes

s->{for(int a[]=new int[26],i=0,l=s.length,t,x;i<l;i+=t){for(t=0;++t+i<l&&s[i]==s[t+i];);System.out.print((t>1?t+"":"")+(++a[x=s[i]-65]>2?s[i]:"@8(63#9#1J<1MN0P9R5+U>u%?ZABCDEFGH!JKiMNOPQR$TU<2XYZ".charAt(x+26*~-a[x])+(x==22?"u":"")));}}

+84 bytes because the rules got changes.. (EDIT: Finally back to my initial 237 bytes.) Replacing WWWW with 222W is easy in Java, but with 4W not.. If only Java had a way to use the regex capture-group for something.. Getting the length with "$1".length(), replacing the match itself with "$1".replace(...), converting the match to an integer with new Integer("$1"), or using something similar as Retina (i.e. s.replaceAll("(?=(.)\\1)(\\1)+","$#2$1")) or JavaScript (i.e. s.replaceAll("(.)\\1+",m->m.length()+m.charAt(0))) would be my number 1 thing I'd like to see in Java in the future to benefit codegolfing.. >.> I think this is the 10th+ time I hate Java can't do anything with the capture-group match..
-78 bytes thanks to @OlivierGrégoire.

I/O is uppercase.

Explanation:

Try it here.

s->{                           // Method with String parameter and no return-type
  for(int a[]=new int[26],     //  Array with 26x 0
          i=0,                 //  Index-integer, starting at 0
          l=s.length,          //  Length
          t,x;                 //  Temp integers
      i<l;                     //  Loop (1) over the characters of the input
      i+=t){                   //    After every iteration: Increase `i` by `t`
    for(t=0;++                 //   Reset `t` to 1
        t+i<l                  //   Inner loop (2) from `t+i` to `l` (exclusive)
        &&s[i]==s[t+i];        //   as long as the `i`'th and `t+i`'th characters are equal
    );                         //   End of inner loop (2)
    System.out.print(          //   Print:
     (t>1?t+"":"")             //    If `t` is larger than 1: print `t`
     +(++a[x=s[i]-65]>2?       //    +If the current character occurs for the third time:
       s[i]                    //      Simply print the character
      :                        //     Else:
       "@8(63#9#1J<1MN0P9R5+U>u%?ZABCDEFGH!JKiMNOPQR$TU<2XYZ".charAt(x
                               //      Print the converted character at position `x`
        +26*~-a[x])            //       + 26 if it's the second time occurring
       +(x==22?"u":"")));      //      And also print an additional "u" if it's 'W'
  }                            //  End of loop (1)
}                              // End of method

Kevin Cruijssen

Posted 2017-10-19T12:47:44.200

Reputation: 67 575

10

JavaScript (ES6), 147 bytes

s=>[[/(.)\1+/g,m=>m.length+m[0]],..."a@b8c(d6e3f#g9h#i1k<l1o0q9s5t+v>x%y?i!lis$v<".match(/../g),["w","uu"],["w","2u"]].map(r=>s=s.replace(...r))&&s

Test Cases

f=
s=>[[/(.)\1+/g,m=>m.length+m[0]],..."a@b8c(d6e3f#g9h#i1k<l1o0q9s5t+v>x%y?i!lis$v<".match(/../g),["w","uu"],["w","2u"]].map(r=>s=s.replace(...r))&&s

;["codegolf","programming","puzzles","passwords","aabaa","www","lllolllolll","jmnpruz"]
.forEach(t=>console.log(t,"->",f(t)))
.as-console-wrapper{max-height:100%!important}

Explanation

Runs through a series of replacements on the input string, s, in the order specified by the challenge. Each item in the series is an array or string, with two items, that is then spread (...r) and passed to s.replace().

s=>[
    [/(.)\1+/g, m=>m.length + m[0]],// first replacement: transform repeated letters
                                    // into run-length encoding

                                    // string split into length-2 partitions and
                                    // spread into the main array
    ..."a@b8c(d6e3f#g9h#i1k<l1o0q9s5t+v>x%y?i!lis$v<".match(/../g),
                                    // next replacements: all single-char replacements.
                                    // "second" versions are placed at the end so they
                                    //    replace the second instance of that char

    ["w","uu"],["w","2u"]           // last replacements: the two "w" replacements
]
.map(r=> s = s.replace(...r))       // run all replacements, updating s as we go
&& s                                // and return the final string

Justin Mariner

Posted 2017-10-19T12:47:44.200

Reputation: 4 746

Very good answer – mdahmoune – 2017-10-19T15:36:59.553

6

05AB1E, 69 bytes

-9 bytes thanks to Emigna

γvygD≠×yÙ}J.•k®zĀÒĀ+ÎÍ=ëµι
•"@8(63#9#1<1095+>%?!i$<"ø'w„uu„2u‚â«vy`.;

Try it online!

Okx

Posted 2017-10-19T12:47:44.200

Reputation: 15 025

You could use 'w„uu„2u‚â – Emigna – 2017-10-19T14:37:45.440

Plz could you verify result for wwww as input? – mdahmoune – 2017-10-19T14:38:35.350

@mdahmoune It outputs 4uu – Okx – 2017-10-19T14:38:50.820

@Emigna Cartesian product, good idea. – Okx – 2017-10-19T14:39:50.890

First part can be γvygD≠×yÙ}J – Emigna – 2017-10-19T14:44:21.950

You also don't need €S – Emigna – 2017-10-19T14:51:33.473

@Emigna Yeah, it was left in from something I had before – Okx – 2017-10-19T14:52:46.197

Thanx for the update ;) – mdahmoune – 2017-10-19T15:33:49.020

6

Perl 5, 152 + 1 (-p) = 153 bytes

s/(.)\1+/(length$&).$1/ge;%k='a@b8c(d6e3f#g9h#i1j!k<l1mio0q9r5s$t+u>v<x%y?'=~/./g;for$i(sort keys%k){$r=$k{$i};$i=~y/jmru/ilsv/;s/$i/$r/}s/w/uu/;s/w/2u/

Try it online!

Xcali

Posted 2017-10-19T12:47:44.200

Reputation: 7 671

Plz what do you mean by (-p)? – mdahmoune – 2017-10-19T16:03:13.797

1@mdahmoune -p is used as an argument to perl at the commandline that automatically reads input from STDIN and prints the contents of $_ at the end of the script. TIO allows that option, and since perl -pe<code> is 1 more byte than perl -e<code> it's counted as one additional byte. – Dom Hastings – 2017-10-19T17:15:13.240

I think you've made a typo, shouldn't the ~ between j~k be an ! instead? Currently it replaced the second occurrence of i with a ~ instead of a !. – Kevin Cruijssen – 2017-10-19T21:27:10.640

@Xcali #testingonproduction – NieDzejkob – 2017-10-21T06:15:02.003

2@NieDzejkob There's no better place. That's the only way you know it will work in production. – Xcali – 2017-10-21T17:44:56.940

4

Probably not the most golfed it could be, but it works.

-6 bytes thanks to ovs

-77 Bytes thanks to NieDzejkob and Jonathan French

Python 3, 329 323 bytes 246 bytes

import re;n=input()
for a in re.finditer('(\w)\\1+',n):b=a.group();n=n.replace(b,str(len(b))+b[0],1)
for A,B,C in[('abcdefghikloqstvxyw','@8(63#9#1<1095+>%?','uu'),('ilsvw','!i$<','2u')]:
	for a,b in zip(A,list(B)+[C]):n=n.replace(a,b,1)
print(n)

Try it online!

reffu

Posted 2017-10-19T12:47:44.200

Reputation: 1 361

1I think you may drop .lower() – mdahmoune – 2017-10-19T17:46:39.723

That makes sense, I wasn't sure whether I needed to handle uppercase or not. – reffu – 2017-10-19T17:54:39.240

321 bytes. – Jonathan Frech – 2017-10-21T04:35:58.903

1320 bytes. – Jonathan Frech – 2017-10-21T04:46:55.710

2

Actually, your answer doesn't work. jjjmjjjj should output 3jm4j but outputs 3jm3jj. Edit: 258 bytes with this problem fixed

– NieDzejkob – 2017-10-21T12:23:18.550

@NieDzejkob 255 bytes.

– Jonathan Frech – 2017-10-21T17:17:35.763

@JonathanFrech 246 bytes except the Python 2 starts getting really similar and I posted a link there with it ported to Python 3 for 192 bytes.

– NieDzejkob – 2017-10-21T18:12:41.933

3

Retina, 166 124 bytes

(.)\1+
$.&$1
([a-y])(?<!\1.+)
¶$&
¶w
uu
T`l¶`@8(63#9#1j<\1mn0\p9r5+u>\w%?_`¶.
([ilsvw])(?<!\1.+)
¶$&
¶w
2u
T`i\lsv¶`!i$<_`¶.

Try it online! Explanation:

(.)\1+
$.&$1

Replace a run of repeated letters with the length and the letter.

([a-y])(?<!\1.+)
¶$&

Match the first occurrence of the letters a to y and mark them with a placeholder.

¶w
uu

Fix the first occurrence of w.

T`l¶`@8(63#9#1j<\1mn0\p9r5+u>\w%?_`¶.

Fix the first occurrence of all the other letters from a to y and delete the placeholders.

([ilsvw])(?<!\1.+)
¶$&

Mark the (originally) second occurrence of the letters i, l, s, v, or w with a placeholder.

¶w
2u

Fix the second occurrence of w.

T`i\lsv¶`!i$<_`¶.

Fix the second occurrence of the other four letters.

Neil

Posted 2017-10-19T12:47:44.200

Reputation: 95 035

Do you think it’s possible to golf it further? – mdahmoune – 2017-10-19T16:07:11.717

@mdahmoune Yes, I think I can save 33 bytes. – Neil – 2017-10-19T16:21:18.747

I up-voted your answer :) it will be great if your save the 33 bytes ;) – mdahmoune – 2017-10-19T16:33:20.023

@mdahmoune Good news, I actually saved 42 bytes! – Neil – 2017-10-19T18:29:45.233

Great, your code is the second shortest ;) – mdahmoune – 2017-10-19T18:42:26.793

3

Haskell, 221 218 213 bytes

($(f<$>words"w2u li i! s$ v< a@ b8 c( d6 e3 f# g9 h# i1 k< l1 o0 q9 s5 t+ v> wuu x% y?")++[r]).foldr($)
f(a:b)(h:t)|a==h=b++t|1>0=h:f(a:b)t
f _ s=s
r(a:b)|(p,q)<-span(==a)b=[c|c<-show$1+length p,p>[]]++a:r q
r s=s

Try it online!

Abuses foldr to run the string through a sequence of string transformations backwards. The sequence "starts" with r which does the repetition count replacement by using span to break the tail of the string when it stops being equal to the head. If the first part of that is non-empty it's a repetition so we print the length +1. Next we curry an argument into f for each character replacement in (reverse) order. The replacements are encoded as a single string with the first character being the character to be replaced and the rest as the string (since the w replacements are multiple characters) to go in its place. I put these encoded strings in one big string separated by spaces so that words can break it into a list for me.

EDIT: Thanks @Laikoni for saving me 5 bytes! That was a clever use of $ I didn't think of. I also didn't know that <- trick.

user1472751

Posted 2017-10-19T12:47:44.200

Reputation: 1 511

Thanx for detailed explanation ;) – mdahmoune – 2017-10-19T19:50:35.137

1You can use (p,q)<-span(==a)b instead of let(p,q)=span(==a)b and p>[] instead of p/=[]. – Laikoni – 2017-10-19T21:03:14.323

2

Save two more bytes by making m pointfree: ($(f<$>words"w2u ... y?")++[r]).foldr($) Try it online!

– Laikoni – 2017-10-19T21:11:54.770

2

R, 224 219 bytes

function(s,K=function(x)el(strsplit(x,"")),u=rle(K(s)))
Reduce(function(x,y)sub(K('abcdefghiiklloqsstvvwwxy')[y],c(K('@8(63#9#1!<1i095$+><'),'uu','2u',K('%?'))[y],x),1:24,paste0(gsub("1","",paste(u$l)),u$v,collapse=""))

Try it online!

Nasty, but the main part is the iterative substitution in the Reduce. sub changes only the first occurrence of the match.

Thanks to JayCe for pointing out a nice golf!

Giuseppe

Posted 2017-10-19T12:47:44.200

Reputation: 21 077

Good job :))))) – mdahmoune – 2017-10-19T22:23:47.723

save 1 byte by rearranging args. Doesn't make a huge difference I know ;) – JayCe – 2018-05-24T18:32:10.487

@JayCe I found some more bytes :-) – Giuseppe – 2018-05-24T18:37:30.100

2

Lua, 173 bytes

s=...for c,r in("uua@b8c(d6e3f#g9h#i1i!jjk<l1limmnno0ppq9rrs5s$t+v>v<wuuw2ux%y?zz"):gmatch"(.)(.u?)"do s=s:gsub(c..c.."+",function(p)return#p..c end):gsub(c,r,1)end print(s)

Try it online!

Ungolfed and explained:

s = ...


--This string contains every character to replace, followed by
--the character(s) it should be replaced with.
--
--It also contains all characters for which repeated sequences
--of them should be replaced by "<number><character>". That is,
--all letters in the alphabet. This way, a single loop can do
--both the "replace repeated characters" and "encode characters"
--operations, saving a for loop iterating over the alphabet.
--
--Characters that shouldn't be replaced will be replaced with
--themselves.
--
--In order to avoid matching half of the "replace u with u"
--command as the replace part of another command, "uu" is placed
--at the beginning of the string. This ensures that only the
--2-character replacements for "w" get an extra "u".

cmdstring = "uua@b8c(d6e3f#g9h#i1i!jjk<l1limmnno0ppq9rrs5s$t+v>v<wuuw2ux%y?zz"


--Iterate over all the search/replace commands.
--The character to replace is in the "c" variable, the string to
--replace it with is in "r".
--
--Due to the dummy search/replace commands (i.e. "mm") placed
--in the string, this loop will also iterate over all letters
--of the alphabet.

for c,r in cmdstring:gmatch("(.)(.u?)") do
	
	--First, replace any occurences of the current letter
	--multiple times in a row with "<number><letter>".
	s = s:gsub(c..c.."+", function(p)
		return #p .. c
	end)
	
	--Then, replace the first occurence of the letter
	--with the replacement from the command string.
	s = s:gsub(c, r, 1)
end

print(s)

Jonathan S.

Posted 2017-10-19T12:47:44.200

Reputation: 423

Lol lua :) good job – mdahmoune – 2017-10-20T06:44:13.183

2

C# (.NET Core), 317, 289, 279 Bytes

p=>{string r="",l=r,h=r,c="a@b8c(d6e3f#g9h#i1i!k<l1lio0q9s5s$t+v>v<wuw2x%y?";int i=0,n=p.Length,d,a=1;for(;i<n;i++){h=p[i]+"";if(h==p[(i==n-1?i:i+1)]+""&&i!=n-1)a++;else{d=c.IndexOf(h);if(d>=0&&d%2<1){l=c[d+1]+"";h=l=="u"?"uu":l;c=c.Remove(d,2);}r+=a>1?a+""+h:h;a=1;}}return r;};

Try it Online!

I hope it's ok to receive a char array as an input and not a string.

Ungolfed:

string result = "", casesCharReplacement = result, currentChar = result, cases = "a@b8c(d6e3f#g9h#i1i!k<l1lio0q9s5s$t+v>v<wuw2x%y?";
int i = 0, n = pas.Length, casesIndex, charAmounts = 1;

// For every char in the pass.
for (; i < n; i++)
{
    currentChar = pas[i] + "";
    // if the next char is equal to the current and its not the end of the string then add a +1 to the repeated letter.
    if (currentChar == (pas[(i == n - 1 ? i : i + 1)] + "") && i != n - 1)
        charAmounts++;
    else
    {
        // Finished reading repeated chars (N+Char).
        casesIndex = cases.IndexOf(currentChar);
        // Look for the replacement character: only if the index is an even position, otherwise I could mess up with letters like 'i'.
        if (casesIndex >= 0 && casesIndex % 2 < 1)
        {
            casesCharReplacement = cases[casesIndex + 1]+"";
            // Add the **** +u
            currentChar = casesCharReplacement == "u"?"uu": casesCharReplacement;
            // Remove the 2 replacement characters (ex: a@) as I won't need them anymore.
            cases = cases.Remove(casesIndex, 2);
        }
        // if the amount of letters founded is =1 then only the letter, otherwise number and the letter already replaced with the cases.
        result += charAmounts > 1 ? charAmounts + ""+currentChar : currentChar;
        charAmounts = 1;
    }
}
return result;

Emiliano

Posted 2017-10-19T12:47:44.200

Reputation: 41

1Yes it’s ok :) for the input – mdahmoune – 2017-10-21T03:01:18.013

2

C++, 571 495 478 444 bytes

-127 bytes thanks to Zacharý

#include<string>
#define F r.find(
#define U(S,n)p=F s(S)+b[i]);if(p-size_t(-1)){b.replace(i,1,r.substr(p+n+1,F'/',n+p)-p-2));r.replace(p+1,F'/',p+1)-p,"");}
#define V(A)i<A.size();++i,c
using s=std::string;s m(s a){s b,r="/a@/b8/c(/d6/e3/f#/g9/h#/i1//i!/k</l1//li/o0/q9/s5//s$/t+/v>/wuu//w2u/x%/y?/";int c=1,i=0;for(;V(a)=1){for(;a[i]==a[i+1]&&1+V(a)++);b+=(c-1?std::to_string(c):"")+a[i];}for(i=0;V(b)){auto U("/",1)else{U("//",2)}}return b;}

the "/a@/b8/c(/d6/e3/f#/g9/h#/i1//i!/k</l1//li/o0/q9/s5//s$/t+/v>/wuu//w2u/x%/y?/" string is used to transform from one character to others. 1 / means that the first "next char" should be replaced by what follow the next /, 2 means that the second "next char" should be replaced by what follows.

Try it online

HatsuPointerKun

Posted 2017-10-19T12:47:44.200

Reputation: 1 891

Great, could you please add a tio.run link ? – mdahmoune – 2017-10-21T09:38:45.743

@mdahmoune TIO link is added, with the code to test for your test cases :) – HatsuPointerKun – 2017-10-21T10:04:28.737

494 bytes, and update the TIO link accordingly if you change it. – Zacharý – 2017-10-22T01:04:10.213

@Zacharý You need to put a space between the macro name and the macro content, otherwise, it throws an error when compiling with C++ 17. Also, do you know how to delete a TIO link ? ( since the old one is useless ) – HatsuPointerKun – 2017-10-22T09:44:01.433

You can't delete a TiO link. But you can remove the reference to it in your answer. – Zacharý – 2017-10-22T13:01:31.973

479 bytes, and if you update the post, update the TIO link accordingly. – Zacharý – 2017-10-22T17:16:30.503

Replace p!=size_t(-1) with p-size_t(-1) to save one byte (ofc update the TIO link afterwards) – Zacharý – 2017-10-22T20:14:35.037

Somehow ... there's more left: 474 bytes

– Zacharý – 2018-05-24T17:27:31.853

446 bytes – Zacharý – 2018-05-24T17:44:15.553

1444 bytes – Zacharý – 2018-05-24T17:50:51.533

1

Perl 5, 123 bytes

122 bytes code + 1 for -p.

Developed independently from @Xcali's answer, but using a very similar process.

s/(.)\1+/$&=~y!!!c.$1/ge;eval"s/$1/$2/"while'a@b8c(d6e3f#g9h#i1i!k<l1lio0q9s5t+v>v<x%y?'=~/(.)(.)/g;s/s/\$/;s/w/uu/;s;w;2u

Try it online!

Dom Hastings

Posted 2017-10-19T12:47:44.200

Reputation: 16 415

1

Python 2, 220 216 194 190 188 bytes

import re
S=re.sub(r'(.)\1+',lambda m:`len(m.group(0))`+m.group(1),input())
for a,b in zip('abcdefghiiklloqsstvvxyww',list('@8(63#9#1!<1i095$+><%?')+['uu','2u']):S=S.replace(a,b,1)
print S

Try it online!

Python 3, 187 bytes

import re
S=re.sub(r'(.)\1+',lambda m:str(len(m.group(0)))+m.group(1),input())
for a,b in zip('abcdefghiiklloqsstvvxyww',[*'@8(63#9#1!<1i095$+><%?','uu','2u']):S=S.replace(a,b,1)
print(S)

Try it online!

TFeld

Posted 2017-10-19T12:47:44.200

Reputation: 19 246

Great golfing ;) – mdahmoune – 2017-10-20T08:38:21.570

186 bytes. You can also easily port this to Python 3 in 192 bytes, but I don't think it should be a separate answer. – NieDzejkob – 2017-10-21T13:36:10.587

@NieDzejkob It seems as though your golfed Python 2 version produces a different output than the OP's current version or your Python 3 version. – Jonathan Frech – 2017-10-21T17:10:41.470

@JomathanFrech sorry, as always testing on production. 188 bytes

– NieDzejkob – 2017-10-21T18:14:50.087

1

Pip, 103 102 bytes

aR:`(.)\1+`#_.B
Fm"abcdefghiiklloqsstvvwwxy"Z"@8(63#9#1!<1i095$+><WU%?"I#Ya@?@maRA:ym@1aR'W"uu"R'U"2u"

Try it online!

Explanation

The code does three steps of transformation:

aR:`(.)\1+`#_.B  Process runs of identical letters

a                1st cmdline argument
 R:              Do this replacement and assign back to a:
   `(.)\1+`       This regex (matches 2 or more of same character in a row)
           #_.B   Replace with callback function: concatenate (length of full match) and
                  (first capture group)
                  Note: #_.B is a shortcut form for {#a.b}

Fm"..."Z"..."I#Ya@?@maRA:ym@1  Do the bulk of rules 2-25

  "..."                        String of letters to replace
       Z"..."                  Zip with string of characters to replace with
Fm                             For each m in the zipped list:
                   @m           First item of m is letter to replace
                a@?             Find its index in a, or nil if it isn't in a
               Y                Yank that into y
             I#                 If len of that is truthy:*
                     aRA:        Replace character in a at...
                         y        index y...
                          m@1     with second item of m

aR'W"uu"R'U"2u"  Clean up substitution
                 In the previous step, the replacements each had to be a single character.
                 This doesn't work for uu and 2u, so we use W and U instead (safe, since
                 uppercase letters won't be in the input) and replace them here with the
                 correct substitutions.
aR'W"uu"         In a, replace W with uu
        R'U"2u"  and U with 2u
                 and print the result (implicit)

* We need to test whether a@?m@0 is nil. It's not enough to test that it's truthy, since 0 is a legitimate index that is falsey. Pip doesn't have a short builtin way to test if a value is nil, but testing its length works well enough in this case: any number will have length at least 1 (truthy), and nil has length of nil (falsey).

DLosc

Posted 2017-10-19T12:47:44.200

Reputation: 21 213