44
\$\begingroup\$

Input

A non-empty encoded string consisting of printable ASCII characters (in the range 32-126), where some missing letters have been replaced with _.

Output

A decoded string of the same length with all letters in lowercase, including the missing ones.

How?

Edit: As mentioned by @Deusovi in the comments, this is a variant of Bacon's cipher.

  • Gather all letters in the original string and group them by 5. Additional letters that do not fit in a full group of 5 are ignored.
  • Convert each group into binary: lowercase = 0, uppercase = 1. This leads to a list of integers.
  • Use each value N in this list to replace each _ in the original string with the N-th letter of the alphabet (0-indexed), in order of appearance.

Example: prOGraMMIng PuZZleS & cOde ____

prOGr --> 00110 -->  6 -->  7th letter = 'g'
aMMIn --> 01110 --> 14 --> 15th letter = 'o'
gPuZZ --> 01011 --> 11 --> 12th letter = 'l'
leScO --> 00101 -->  5 -->  6th letter = 'f'

By replacing the missing letters and converting everything back to lowercase, the original string is unveiled:

programming puzzles & code golf

This is the expected output.

Clarifications and rules

  • The missing letters are guaranteed to appear at the end of the string. More formally: there will never be any letter after the first _ in the input string. However, there may be other printable ASCII characters such as spaces and punctuation marks.
  • The input is guaranteed not to contain any useless capital letter: all capital letters are bits set to 1 which are required to decode the missing letters. Everything else is in lowercase.
  • The input string is guaranteed to be valid. Especially:
    • It will always contain enough full groups of 5 letters to decode the underscores.
    • The binary-encoded integers are guaranteed to be in the range [0-25].
  • There may be no _ at all in the input string, in which case you just have to return the input.
  • This is , so the shortest answer in bytes wins!

Test cases

Input : hello!
Output: hello!

Input : helLO, worl_!
Output: hello, world!

Input : i aM yoUr faTh__.
Output: i am your father.

Input : prOGraMMIng PuZZleS & cOde ____
Output: programming puzzles & code golf

Input : Can YOu gUesS tHE ENd oF This ____?
Output: can you guess the end of this text?

Input : THe qUICk brown FOx JUMps oVEr the la__ ___.
Output: the quick brown fox jumps over the lazy dog.

Input : RoadS? wHERe we're goinG WE doN't need _____.
Output: roads? where we're going we don't need roads.

Input : thE greatESt Trick thE DeVIl EVer PUllEd wAs CONvInciNg tHe WorLD h_ ____'_ _____.
Output: the greatest trick the devil ever pulled was convincing the world he didn't exist.

Some extra test-cases:

Input : BInar_
Output: binary

Input : 12 MonKey_
Output: 12 monkeys

Input : hyPerbolIZ__
Output: hyperbolized

Input : {[One Last Test ca__]}
Output: {[one last test case]}
\$\endgroup\$
  • \$\begingroup\$ Should we only consider as many groups of 5 as there are underscores in the input? \$\endgroup\$ – Esolanging Fruit May 12 '18 at 18:10
  • \$\begingroup\$ In that case, the rule when there's no _ in the input string is a bit of a special case. \$\endgroup\$ – Esolanging Fruit May 12 '18 at 18:17
  • 1
    \$\begingroup\$ Ooh, Bacon cipher! \$\endgroup\$ – Deusovi May 12 '18 at 19:38
  • 1
    \$\begingroup\$ @SztupY As The input is guaranteed not to contain any useless capital letter, in case there is no underscore there also won't be a capital letter. \$\endgroup\$ – Laikoni May 14 '18 at 11:03
  • 1
    \$\begingroup\$ @KirillL. Yes, anything in [32-126]. I've added another test case. \$\endgroup\$ – Arnauld May 14 '18 at 12:16

26 Answers 26

19
\$\begingroup\$

05AB1E, 18 bytes

Code:

áS.u5ôJC>.bv'_y.;l

Uses the 05AB1E encoding. Try it online!

Explanation:

á                       # Remove non-letters from the input string.
 S                      # Split the result into individual characters.
  .u                    # Check if is uppercase for each character.
    5ôJ                 # Split into binary numbers of length 5.
       C                # Convert from binary to decimal.
        >               # Add one.
         .b             # Map 1 → A, 2 → B, 3 → C, ..., 25 → Y, 26 → Z.
           v            # For each letter:
            '_y.;       #   Replace the first occurrence of '_' with the current letter.
                 l      #   Convert the string to lowercase.
\$\endgroup\$
8
\$\begingroup\$

Python 2, 113 bytes

s=input()
i=k=0
for c in s:
 if c.isalpha():k+=k+(c<'a');i+=1;s=s.replace('_',chr(k%32+97),i%5<1)
print s.lower()

Try it online!

\$\endgroup\$
8
\$\begingroup\$

Perl 5 -pF -MList::Util=sum, 75 bytes

@a=grep!/\W|\d/,@F;s!_!(a..z)[sum map{a gt shift@a&&16/2**$_}0..4]!eg;$_=lc

Try it online!

Explanation:

  • -pF reads a line of input into the variable $_ and, split into characters, into the array @F.
  • @a=grep!/\W|\d/,@F sets the array @a equal to those members of @F that don't satisfy the regex \W|\d. \W is anything but letters, numbers, and _; \d is numbers. So \W|\d is anything but letters and _, and @a has all the letters and _ characters. We will wind up never examining the _ characters in @a. (Note that this only works because the input is guaranteed ASCII.)
  • map{a gt shift@a&&16/2**$_}0..4 does the following for 0 through 4: It shifts the next element off of @a, shortening it, and evaluates whether a is asciibetically greater than that element (i.e. whether that element is uppercase). If so, && isn't short-circuited, so we get 16 divided by 2 to rhe power of the input value (0 through 4). Otherwise && is short-circuited and we get 0. map returns the list of five numbers to sum, which adds them.
  • That's the element we want from the list a..z, and that's what we get from (a..z)[…].
  • s!_!…!eg converts each _ in $_, in turn, to the appropriate letter.
  • $_=lc converts $_ to the lowercase version of itself, and -p prints it.
\$\endgroup\$
6
\$\begingroup\$

J, 62 61 bytes

tolower u:@]`(I.@t=.'_'=[)`[}+/@t$97+_5#.\3|0 2 4-.~'@Z`z'&I.

Try it online!

\$\endgroup\$
5
\$\begingroup\$

Jelly,  28 27  26 bytes

-1 thanks to Erik the Outgolfer & dylnan

Not a very Jelly-friendly challenge!

ḟŒs$Ƈ<”[s5Ḅ+97Ọż@ṣ”_$FṁLŒl

A monadic link accepting and returning lists of characters.

Try it online!

How?

ḟŒs$Ƈ<”[s5Ḅ+97Ọż@ṣ”_$FṁLŒl - Link: list of characters    e.g. "MfUNE_?"  (shorthand for ['M','f','U','N','E','_','?'])
    Ƈ                      - filter keep each if:
   $                       -   last two links as a monad:
 Œs                        -     swap-case
ḟ                          -     filter discard
                           - ...i.e. keep A-Z,a-z since they change when the case is swapped
                           -                                  "MfUNE"
      ”[                   - literal character                '['
     <                     - less than? (i.e. is upper-case?) [1,0,1,1,1]
        s5                 - split into fives                 [[1,0,1,1,1]]
          Ḅ                - from base two (vectorises)       [[23]]
           +97             - add (vectorises) ninety-seven    [[120]]
              Ọ            - from ordinals (vectorises)       [['x']]
                    $      - last two links as a monad:
                  ”_       -   literal character              '_'
                 ṣ         -   split at                       [['M','f','U','N','E'],['?']]
               ż@          - swapped @rgument zip             [[['M','f','U','N','E'],'x'],['?']]
                     F     - flatten                          "MfUNEx?"
                       L   - length (of input)                7
                      ṁ    - mould like                       "MfUNEx?"
                           - ...removes any excess characters
                        Œl - lower-case                       "mfunex?"
\$\endgroup\$
5
\$\begingroup\$

Retina, 91 90 bytes

T`l`a
T`L`A
[^Aa]

L`.{5}
A
aA
+`Aa
aAA
+T`_lA`l_`[^A]A
^
$+¶
+`_(.*)¶a+(.)
$2$1
0G`
T`L`l

Try it online! Explanation:

T`l`a
T`L`A
[^Aa]

Translate lowercase letters to a and uppercase letters to A, deleting everything else.

L`.{5}

Split the Aas into groups of 5.

A
aA
+`Aa
aAA

Convert from binary into unary, treating A as 1 and a as 0. Since there were 5 Aas originally, there are 5 as left, plus a number of As depending on the desired position in the alphabet.

+T`_lA`l_`[^A]A

Increment the last a according to the number of following As.

^
$+¶

Prepend the original input.

+`_(.*)¶a+(.)
$2$1

Replace any _s with the next decoded letter.

0G`

Remove any spare decoded letters.

T`L`l

Lowercase everything.

Retina 0.8.2, 117 bytes

.+
$&¶$&
T`L`l`^.*
T`l`a`.*$
T`L`A
T`aAp`aA_`.*$
(.*¶)?.{5}
$&;
A
aA
+`Aa
aAA
+T`_lA`l_`[^A]A
+`_(.*¶)a+(.);
$2$1
1G`

Try it online! Explanation:

.+
$&¶$&

Duplicate the input.

T`L`l`^.*

Lowercase the first copy.

T`l`a`.*$

Translate lowercase letters to a in the second copy.

T`L`A

Translate uppercase letters to A. These must be in the second copy because the first copy was already lowercased.

T`aAp`aA_`.*$

Delete everything else in the second copy.

(.*¶)?.{5}
$&;

Split the second copy (now just Aas) into groups of 5.

A
aA
+`Aa
aAA
+T`_lA`l_`[^A]A
+`_(.*¶)a+(.);
$2$1
1G`

Decode the letters and insert them as before.

\$\endgroup\$
5
\$\begingroup\$

APL (Dyalog Unicode), 46 bytesSBCS

Anonymous lambda, Assumes ⎕IO (Index Origin) to be 0.

{_←'_'=⊢⋄819⌶A[2⊥⍉(+/_⍵)5⍴A∊⍨⍵∩A,819⌶A←⎕A]@_⍵}

Try it online!

{} two-statement function; is the argument, separates statements

 argument (no-op function)
'_'= where equal to an underscore (i.e. a Boolean mapping function)
_← assign that function to _

A[]@_⍵ put the following characters of A at positions of underscores in the argument
  ⎕A the uppercase Alphabet
  A← assign that to A
  819⌶ lowercase it (819 ≈ BIg, with no left argument means not big, i.e. lowercase)
  A, prepend the uppercase alphabet; this gives us all letters
  ⍵∩ intersection of the argument and that; just the letters of the argument
  A∊⍨ which of those are members of the uppercase alphabet; uppercase bits
  ()5⍴reshape that to the following number of rows, and five columns:
   _⍵ the mask of underscores in the argument
   +/ sum that; number of underscores
   transpose (to treat each row as a number rather than as a bit position)
  2⊥ evaluate as base-2
819⌶ lowercase everything

\$\endgroup\$
5
\$\begingroup\$

Scala, 189 bytes

def f(s:Array[Char])={var j=0;s.zipWithIndex.collect{case(95,i)=>s(i)=(Integer.parseInt(s.filter(_.isLetter)slice(j,j+5)map(k=>if(k<91)1 else 0)mkString,2)+97)toChar;j+=5};s.map(_.toLower)}

Try it online!

Explanation:

def f(s: Array[Char]) = {                // takes a String in input
  var j = 0                              // j stores at which block of 5 letters we're currently at
  s.zipWithIndex.collect {               // Array('h', 'e', ...) => Array(('h', 0) ('e', 1), ...) and we apply a collect transformation (filter/map)
    case (95, i) =>                      // we only handle cases where the char is '_' (95)
      s(i) = (                           // we modify the char at index i with the following
        Integer.parseInt(                // Integer.parseInt("00110", 2) = 6
          s                              //
            .filter(_.isLetter)          // filter out non letter chars (spaces, punct, figures, ...) from the input string (thanks @Arnauld for the fix)A
            .slice(j, j+5)               // "substring" the array to the block of 5 letters in question
            .map(                        // map on the current block of 5 letters
              k =>                       // the index of the next char in the block f 5 (e.g. 13)
                if (k < 91) 1 else 0     // if the current char is upper case (<91) then we replace it by a bit true, otherwise by a bit false
            )mkString,                   // Array(0, 1, 1, ...) => "011..."
          2                              // cast string to binary
        )                                //
        + 97                             // +97 to create a lower case char
      )toChar                            // cast from int to char
      j += 5                             // update the starting index of the next block of 5 letters
    }                                    //
  s.map(_.toLower)                       // return the updated seq of chars all in lower case
}                                        //
\$\endgroup\$
4
\$\begingroup\$

JavaScript (Node.js), 125 124 bytes

x=>x.replace(s=/./g,c=>parseInt(c,36)>9?c.toLowerCase(s+=+(c<{})):c=='_'?('0b'+s.slice(4,9)-~9).toString(36,s=s.slice(5)):c)

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Jelly, 26 bytes

xn¥Œs<”[s5Ḅ‘ịØaṛi”_ḟ0Ɗ¦ƒŒl

Try it online!

Different approach from Jonathan Allan's. EDIT: So, I, uh, apparently thought of the same byte reduction as Jonathan Allan, so it doesn't hurt to mention his name again.

\$\endgroup\$
3
\$\begingroup\$

CJam, 43 bytes

q'_/_0={el_eu=!},_eu.=5/2fb65f+:c1$,(<.+:el

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Clean, 180 ... 150 bytes

import StdEnv
?s=['a'+sum[i\\i<-:""&c<-s|c<'a']: ?(drop 5s)]
@['_':b][x:y]=[x: @b y]
@[a:b]z=[toLower a: @b z]
@e _=e
$s= @s(?(filter isAlpha s))

Try it online!

Defines the function $ :: [Char] -> [Char] with @ :: [Char] [Char] -> [Char] as a helper to replace underscores, and ? :: [Char] -> [Char] as a helper to generate the replacement characters.

\$\endgroup\$
  • \$\begingroup\$ How does the i<-:"" part work? Are chars implicitly converted to numbers when summing or adding them? \$\endgroup\$ – Laikoni May 14 '18 at 12:48
  • \$\begingroup\$ @Laikoni no, there's no implicit conversion. You can add and subtract Chars though. \$\endgroup\$ – Οurous May 14 '18 at 20:31
3
\$\begingroup\$

JavaScript (Node.js), 100 bytes

s=>s.toLowerCase(c=/[a-z]/gi).replace(/_/g,_=>(g=n=>n?(c.exec(s)<{})*n+g(n>>1):10)(16).toString(36))

Try it online!

Thanks to @Arnauld, saves 2 bytes.

\$\endgroup\$
  • 1
    \$\begingroup\$ @Arnauld you are right. edited to /[a-z]/gi now. \$\endgroup\$ – tsh May 14 '18 at 7:27
3
\$\begingroup\$

R, 153 135 113 bytes

function(s,S=utf8ToInt(s)){S[S==95]=2^(4:0)%*%matrix(S[S%in%c(65:90,97:122)]<95,5)+97
cat(tolower(intToUtf8(S)))}

Try it online!

Issues some warnings with the use of matrix but that shouldn't affect the result. Also issues warnings as [<- assignment will remove extraneous assigned objects by default.

40(!) bytes down thanks to JayCe's improvements

\$\endgroup\$
  • \$\begingroup\$ I don't think you need ,length(L)%/%5 \$\endgroup\$ – JayCe May 14 '18 at 17:05
  • \$\begingroup\$ Also no need to define L? \$\endgroup\$ – JayCe May 14 '18 at 17:07
  • \$\begingroup\$ @JayCe okay well today I learned that [<- will throw out elements past the length of the indexes... \$\endgroup\$ – Giuseppe May 14 '18 at 17:21
  • \$\begingroup\$ Me too actually! \$\endgroup\$ – JayCe May 14 '18 at 17:26
  • \$\begingroup\$ Translated your approach to intToUtf8 \$\endgroup\$ – JayCe May 14 '18 at 19:03
3
\$\begingroup\$

C (gcc), 111 109 101 100 bytes

Edit: Added lowercasing per @FrownyFrog's comment; thanks to Lynn, Christoph and user5329483 for their suggestions!

f(s,t,i)char*s,*t;{for(t=s;t=strchr(t,95);*t=i+1)for(i=3;i<64;s++)isalpha(*s)?i=2*i|*s<97,*s|=32:0;}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ You can save 2 bytes with i+=i+(*s<97). \$\endgroup\$ – Lynn May 13 '18 at 9:51
  • \$\begingroup\$ You could abolish j by introducing a marker bit in i and rewriting the second for as for(i=1;i<32;s++). And compensate the extra 32 in the outer for. As a newbee here I count a seven byte spare. \$\endgroup\$ – user5329483 May 14 '18 at 16:40
  • \$\begingroup\$ Found another byte: for(i=3;i<96;s++) brings the 65 down to a single-digit number, aka 1. \$\endgroup\$ – user5329483 May 15 '18 at 17:56
2
\$\begingroup\$

Go, 219 217 192 210 209 156 bytes

Saved 25 bytes thanks to @Lynn! Saved 53 bytes thanks to @ovs!

Had to lose 18 bytes because of a bug with strings with no underscores :(

func p(s string){b:=0;n:=0;for _,c:=range s{if IsLetter(c){b+=b;if IsUpper(c){b+=1};n++;s=g.Replace(s,"_",string('a'+b%32),(5-n%5)/5)}};Print(g.ToLower(s))}

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Stax, 22 bytes

â╟▓ïMeee¶▐f◄┴≈┘n╛äyΩ○N

Run and debug it

The general approach is a regular expression replacement of "_" using a callback function that slices letters of the inputs to compute each replacement character.

v       convert to lower case
'_      "_" string literal
{       begin block for regex replacement
  yVl|& all the letters only from the original input
  5/    split into chunks of 5
  i@    keep the ith one, where i is the 0-based number of times this block has run
  {97<m map 5-letter chunk to bits to indicate which are lowercase
  :b    decode as 5-bit integer
  97+]  add 97 and wrap in array to convert to lower case character
}       end block for regex replacement
R       do regex replacement

Run this one

\$\endgroup\$
1
\$\begingroup\$

Red, 247 bytes

func[s][a: charset[#"a"-#"z"#"A"-#"Z"]v: copy""parse s[any[copy c a(append v to-string c)|
skip]]k: 0 t: copy""repeat n(length? v)/ 5[c: 0 p: 16
loop 5[if v/(k: k + 1) <#"a"[c: c + p]p: p / 2]append t#"a"+ c]foreach c
t[replace s"_"c]lowercase s]

Try it online!

More readable:

f: func[s][
    a: charset[#"a"-#"z"#"A"-#"Z"]
    v: copy ""
    parse s[any[copy c a(append v to-string c)| skip]]
    k: 0
    t: copy ""
    repeat n (length? v) / 5[
        c: 0
        p: 16
        loop 5[
            if v/(k: k + 1) < #"a" [c: c + p]
            p: p / 2
        ]
        append t #"a" + c
    ]
    foreach c t[replace s "_" c]
    lowercase s
]
\$\endgroup\$
1
\$\begingroup\$

Java 10, 186 bytes

s->{var b="";for(int i=0,c;i<s.length();)if((b+=(c=s.charAt(i++))>64&c<91?1:c>96&c<123?0:"").length()>4)s=s.replaceFirst("_",(char)(97+Byte.valueOf(b,2))+(b=""));return s.toLowerCase();}

Try it online.

Explanation:

s->{                            // Method with String as both parameter and return-type
  var b="";                     //  Binary-String, starting empty
  for(int i=0,c;i<s.length();)  //  Loop over the characters of the input-String
    if((b+=(c=s.charAt(i++))>64&c<91?
                                //   If the current character is a lowercase letter:
            1                   //    Append "1" to the binary-String
           :c>96&c<123?         //   Else-if it's an uppercase letter:
            0                   //    Append "0" to the binary-String
           :                    //   Else (not a letter):
            "")                 //    Append nothing to the binary-String
       .length()>4)             //   And if the length is now 5:
      s=s.replaceFirst("_",     //    Replace the first "_" in the input-String with:
           (char)(97+Byte.valueOf(b,2))
                                //     The binary-String as character
           +(b=""));            //    And reset the binary-String
  return s.toLowerCase();}      //  Return the modified input-String as lowercase
\$\endgroup\$
1
\$\begingroup\$

Ruby, 107 106 103 bytes

->s{s.chars.map{|c|c !~/\W|\d/?c<?a?1:0:p}.join.scan(/.{5}/){|b|s[?_]&&=(b.to_i(2)+97).chr};s.downcase}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Japt, 25 bytes

r'_@r\L mè\A sTT±5 ÍdIÄÃv

Try it


Explanation

r'_                           :Replace underscores
   @                          :Pass each match through a function
    r                         :  From original input remove
     \L                       :    /[^a-zA-Z]/g
        m                     :  Map
         è                    :    Count
          \A                  :      /[A-Z]/g
             s                :  Slice
              T               :    From index T (initially 0)
               T±5            :    To index T+=5
                   Í          :  Convert from base-2 string to base-10 integer
                     IÄ       :  Add 64+1
                    d         :  Get character at that codepoint
                       Ã      :End function
                        v     :Lowercase
\$\endgroup\$
1
\$\begingroup\$

Pyth, 36 bytes

Km@Gim!}kGd2c@+r1GGQ5VQp?qN\_.(KZr0N

Try it here

Explanation

Km@Gim!}kGd2c@+r1GGQ5VQp?qN\_.(KZr0N
             @+r1GGQ                   Get the letters from the input...
            c       5                  ... in chunks of 5.
 m        d                            For each chunk...
     m!}kG                             ... check if each letter is uppercase...
    i      2                           ... converted to binary...
  @G                                   ... and get the corresponding letter.
                     VQp               For each character in the input...
K                       ?qN\_.(KZ      ... if the character is '_', replace it...
                                 r0N   ... otherwise, lowercase it.
\$\endgroup\$
1
\$\begingroup\$

Python 3.5, 296 bytes

u=input();f=u.find('_');m=''.join([c for c in u if c.isalpha()]);z=[chr(int(''.join(['0'if o.islower() else'1' for o in l]),2)+65)for l in[m[h:h+5]for h in range(0,len(m),5)]if len(l)==5];[z.insert(v,d)for v,d in enumerate(u[f:])if d!="_"];u=list(u);u[f:]=z[:len(u[f:])];print(''.join(u).lower())

Try it online

First code golf :)

(I know its not small in bytes, I was just having fun making a 1 line code)

Here is the explanation:


User input

u=input()


Finds the index of the first _ in the string and stores it

f=u.find('_')


strips string of all non-alpha characters

m=''.join([c for c in u if c.isalpha()])


Splits the alpha string into an array with each element consisting of 5 characters

Ex. ['THeqU', 'ICkbr', 'ownFO', 'xJUMp', 'soVEr', 'thela']

Then converts lowercase characters to 0 and uppercase characters to 1

Ex. ['11001', '11000', '00011', '01110', '00110', '00000']

and converts the binary string to an integer, adds 65 and converts that to a character

Ex. ['z', 'y', 'd', 'o', 'g', 'a']

z=[chr(int(''.join(['0' if o.islower() else '1' for o in l]),2)+65) for l in [m[h:h+5] for h in range(0,len(m),5)] if len(l)==5]


finds all characteres after the first _ and pushes them into the array z at their respective locations (defined above)

Ex. ['z', 'y', ' ', 'd', 'o', 'g', '.', 'a']

[z.insert(v,d) for v,d in enumerate(u[f:]) if d!="_"]


split our string into a list of characters

u=list(u)


slice our string from the first _ to the end of the list and replace it with the array z. I also had to slice the array z to the length of the split string from the first _ to the end because I got an extra character in the lazy dog example (the "a" at the end of the examples above)

u[f:]=z[:len(list(u[f:]))]


*print out the answer *

print(''.join(u).lower())


\$\endgroup\$
  • \$\begingroup\$ There's more to golfing than just getting everything on one line. 165 bytes \$\endgroup\$ – Jo King May 16 '18 at 10:27
  • \$\begingroup\$ You can remove the space between o.islower() and else, and I think '1' and for. Also, you can change if d!="_" to if"_"!=d, but the above comment already does that. \$\endgroup\$ – Zacharý May 17 '18 at 12:52
1
\$\begingroup\$

Haskell, 165 bytes

g""
import Data.Char
f t(x:s)('_':r)=x:f t s r
f[0,a]s r=g(s++[chr a])r
f[n,a]s(c:r)=toLower c:f[div n$1+sum[1|isAlpha c],a+sum[n|isUpper c]]s r
f _ s e=e
g=f[16,97]

Try it online! Example usage: g"" "BInar_" yields "binary".

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 121 bytes

switch -r($args|% t*y){_{$_=$a[$n++]+97}[a-z]{$x+=$x+($_-le96);if(!(++$i%5)){$a+=,$x;$x=0};$_=$_-bor32}.{$r+=[char]$_}}$r

Try it online!

Less golfed:

switch -Regex ($args|% toCharArray){
    _ {                     # is underscore
        $_=$a[$n++]+97      # get a char from the array of letter
    }

    [a-z] {                 # is letter
        $x+=$x+($_-le96)    # $x=2*$x+($_-le96)
        if(!(++$i%5)){      # if(++$i%5 -eq 0)
            $a+=,$x         # add an element to the array of letters
            $x=0            # init
        }
        $_=$_-bor32         # to lower
    }

    . {                     # is any char ('_' and letters included)
        $r+=[char]$_        # add the char to result
    }
}
$r
\$\endgroup\$
0
\$\begingroup\$

Perl 5 -p, 78 bytes

for$h(s/\W|\d//gr=~y/a-z/0/r=~y/A-Z/1/r=~/.{5}/g){s%_%chr 65+oct"0b$h"%e}$_=lc

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I fixed it with 3 more bytes, which makes your answer a bit better under the current rules. \$\endgroup\$ – Xcali May 15 '18 at 13:35
  • \$\begingroup\$ Not better but different. Each language + options is considered separately, not competing with the same language + other options, as I understand it. \$\endgroup\$ – msh210 May 21 '18 at 5:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.