17
\$\begingroup\$

Geobitsian language is a new perversion of English where a word is broken into segments that each must start with a different letter. Then every time one of those starting letters appears in another string, it is replaced with its entire corresponding segment, maintaining capitalization.

This process is called Geobitsizing.

For example the word "Geobits" could be broken into geo bits, and the nonsense poem

Algy met a Bear
A Bear met Algy
The Bear was bulgy
The bulge was Algy

would be Geobitsized with it as

Algeoy met a Bitsear
A Bitsear met Algeoy
The Bitsear was bitsulgeoy
The bitsulgeoe was Algeoy

because every g becomes geo, every G (though there are none) becomes Geo, every b becomes bits, and every B becomes Bits.

Note that each substitution is performed with respect to the original string, not any intermediate step. e.g. if geo had been gbo instead, the b's created would not replaced with bits.

Challenge

Write a program or function that can generate Geobitsian language.

Take in a single-line string made of lowercase letters (a-z) and spaces. This will be the word used as the Geobitsizing argument, with the spaces separating the segments. You can assume:

  • Segments will not be empty. So spaces will not neighbor each other nor be at the start or end of the string.
  • Each segment starts with a different letter. Thus there cannot be more than 26.

For example, some valid segmented strings you must support are geo bits, butt ner, alex, and do o r k nob (single letter segments have no effect but are valid). But geo , butt ner, Alex, and do o r k n ob are invalid.

Your program or function also needs to take in another arbitrary string to apply the Geobitsizing to, and print or return the resulting Geobitsian language.

  • You can assume this string only contains newlines and printable ASCII.

  • Remember that letter cases must be preserved from the input to the output.

Here are some more examples using no pro gr am m ing as the Geobitsizing argument:

[empty string][empty string]

iing

IIng

Mmmm, mmm... MmmmMMM: m&m!Mmmm, mmm... MmmmMMM: m&m! (no change)

People think bananas are great, don't you?Proeoprole thingnok bamnoamnoams amre grreamt, dono't you?

Pet a Puppy
Google Wikipedia

Proet am Prouproproy
Groogrle Wingkingproedingam

Note that the results should be identical no matter how the argument is arranged, e.g. ing pro m no am gr should yield the same results as above.

The shortest code in bytes wins.

\$\endgroup\$
9
  • \$\begingroup\$ Can we take the "Geobitsizing argument" as an array? e.g. ["no", "pro", "gr", "am", "m", "ing"] \$\endgroup\$
    – Downgoat
    Commented Jun 7, 2016 at 4:21
  • \$\begingroup\$ @Upgoat Sorry but no. \$\endgroup\$ Commented Jun 7, 2016 at 4:22
  • \$\begingroup\$ @Upgoat Try \\b${l}(\\S+) although that does cost you 5 bytes. \$\endgroup\$
    – Neil
    Commented Jun 7, 2016 at 9:12
  • 4
    \$\begingroup\$ -1 for arbitrary input requirement of a space-separated string. \$\endgroup\$ Commented Jun 7, 2016 at 12:44
  • 2
    \$\begingroup\$ Suggested test case: abra cadabra, !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ That should cover all edge cases, and there are a lot of them if one tries to use regexes... \$\endgroup\$
    – Dennis
    Commented Jun 7, 2016 at 18:13

17 Answers 17

6
\$\begingroup\$

Jelly, 18 bytes

ṣ⁶;Œu1¦€$;©ZḢiЀị®

Try it online!

Alternative version, 15 bytes

Jelly's title case function had a bug; it didn't capitalize the first word. That has been fixed, so the following works now.

ṣ⁶;Œt$;©ZḢiЀị®

This code does the same as in the competing version, except that Œt (title case) replaces the conditional uppercasing achieved by Œu1¦€.

How it works

ṣ⁶;Œu1¦€$;©ZḢiЀị®  Main link. Left argument: w (words). Right argument: s (string)

ṣ⁶                  Split w at spaces.
        $           Combine the two links to the left into a monadic chain.
       €              Map over the words.
   Œu1¦                 Uppercase the item at index 1.
  ;                   Append the result to the unmodified words.
         ;          Append all characters in s to the list of words.
          ©         Copy the result to the register.
           Z        Zip/transpose, grouping the first chars into the first list.
            Ḣ       Head; extract the list of first characters.
             iЀ    Find the first index of each character in s.
                ị®  Select the characters/strings from the list in the register
                    that are at those indices.
\$\endgroup\$
5
\$\begingroup\$

Python 3, 71 bytes

lambda w,s:s.translate({ord(t[0]):t for t in(w+' '+w.title()).split()})

Test it on Ideone.

How it works

In Python 3, the built-in str.translate takes a string and a dictionary, and replaces each character in the string whose code point is a key of that dictionary with the corresponding value, which may be a string, an integer or None (equivalent to the empty string).

Converting the string of words w to title case (i.e., capitalizing the first letter of each word) and appending it to the result of w+' ' creates a string of space separated words with lower- and uppercase version (first letter). Without a second argument, str.split splits at whitespace, so (w+' '+w.title()).split() creates the list of all words.

Finally, the dictionary comprehension {ord(t[0]):t for t in...} turns each word t into a dictionary entry with key ord(t[0]) (code point of the first letter) and value t, so str.translate will perform the intended substitutions.

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

Retina, 36 bytes

Byte count assumes ISO 8859-1 encoding.

i`(?<=^.*\b\2(\w+)[^·]*?(\w))
$1
A1`

Try it online!

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

Python, 126 99 95 81 bytes

Alot thanks to Dennis:

lambda G,S,j=''.join:j(s+j(g[1:]for g in G.split()if g[0]==s.lower())for s in S)

Edit1: don't need to append to a temporary

Edit2: S may contain uppercase...

Edit3: don't duplicate G

Edit4: compressed a little bit more and shoved it into one line

Edit5: using unnamed lambda and j=join' '

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

Pyth, 19 bytes

.rzsC_hMBsm,rd0rd3c

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ We can't take the geobitsizing argument as an array, unfortunetly \$\endgroup\$
    – Downgoat
    Commented Jun 7, 2016 at 4:26
  • \$\begingroup\$ Sorry, didn't notice. \$\endgroup\$
    – Leaky Nun
    Commented Jun 7, 2016 at 4:31
2
\$\begingroup\$

Vim, 46 keystrokes

Ugly, and Hacky.

A <esc>:s/\<\w/:%s\/\0\\c\/\\0/g<cr>:s/ /eg<C-v><Cr>/g<cr>dgg@"
\$\endgroup\$
2
  • \$\begingroup\$ Why not in V? D: \$\endgroup\$
    – Downgoat
    Commented Jun 7, 2016 at 14:52
  • \$\begingroup\$ @Upgoat Cause it's a buggy mess. \$\endgroup\$
    – DJMcMayhem
    Commented Jun 7, 2016 at 15:14
2
\$\begingroup\$

JavaScript ES6, 67 63 70 bytes

g=>s=>s.replace(/\S/g,l=>l+(g.match(`\\b\\${l}(\\S+)`,'i')||[,""])[1])

Test this on Firefox. bugs are making this longer than I'd like

Explanation

function(gbarg, str) {
   return str.replace(/\S/g, function(chr) { // Replace non-whitespace w/...
        return chr + (
         gbarg.match(`\\b\\${l}(\\S+)`,'i')  // That word in the gbstr
        ||[,""])[1]                          // if not in gbstr, use blank str
   });
}
\$\endgroup\$
1
  • \$\begingroup\$ f("abracadabra")("1Dbw") returns "1abracadabraDbracadabrababracadabrawbracadabra". \$\endgroup\$
    – Dennis
    Commented Jun 7, 2016 at 17:59
2
\$\begingroup\$

Pyth, 18 16

MsXGhMJcjdrBH3)J

Try it here

Defines a function g that performs the geobitsising. As a program this would be a bit shorter if the second string is single line, but multiline input isn't worth it:

sXwhMJcjdrBz3)J

The general idea here was to title case the geobitsian string and append that to the original string. Then split that on spaces and for each string, take the first letter and map it to the string it represents. That way X will turn the first letter of each word into the full word.

\$\endgroup\$
2
  • \$\begingroup\$ Did you just... outgolf Dennis? \$\endgroup\$ Commented Jun 8, 2016 at 13:44
  • \$\begingroup\$ @BojidarMarinov If you count Dennis using some other language that had a bug in it as outgolfing, then yes ;) \$\endgroup\$ Commented Jun 8, 2016 at 13:57
2
\$\begingroup\$

Python 2, 83 78 bytes

lambda w,s:''.join(c+w[(' '+w).find(' '+c.lower()):].split()[0][1:]for c in s)

Test it on Ideone.

How it works

We iterate over all characters c in the string s.

We prepend a space to the string of words w, then search for a occurrence of lowercased c, preceded by a space.

  • If such an occurrence exists, find will return the index of the space in the string ' '+w, which matches the index of c in w.

    w[...:] thus returns the tail of w, starting from the word with first letter c. split() splits the tail at spaces, [0] selects the first chunk (the word) and [1:] removes its first letter.

    After prepending c to the previous result, we obtain the correctly cased word that starts with c.

  • If no word begins with c, find will return -1.

    Thus, w[...:] yields the last character of w, split() wraps it in an array, [0] undoes the wrapping, and [1:] removes the only character from the string.

    After prepending c, we obtain the singleton string whose character is c, so the whole operation is a no-op.

Finally, ''.join concatenates all resulting strings, returning the Geobitsized version of s.

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

TypeScript's type system, 145 bytes

//@ts-ignore
type F<I,S,O="">=S extends`${infer C}${infer R}`?F<I,R,`${O}${C}${` ${I} `extends`${any} ${Lowercase<C>}${infer Z} ${any}`?Z:""}`>:O

Try it online: TypeScript Playground

This is a recursive generic type F<I, S> where I is a string-type representing the space-separated segments string, and S is the other string type. The //@ts-ignore comment is used to dismiss compiler errors.

Explanation:

The idea is to recursively loop through S, appending each character to a string O which begins empty and fills up with the final result.

Loop over the string S until it is empty by pattern-matching it against `${infer C}${infer R}` (which makes the first character C and the rest R) and recursing with F<I,R, ...> (keeping I the same and using R for the string). If the pattern-match fails because we have exhausted S, return the type parameter O which contains the result.

For the replacing logic, we attempt to pattern match ` ${I} ` (I surrounded by a space on both ends) against `${any} ${Lowercase<C>}${infer Z} ${any}` (which says match anything, a space, C converted to lowercase, some characters which are assigned to Z, another space, and anything). This effectively finds the suffix Z of the segment which starts with C. Then, Z—or nothing, if the match failed—is then appended to C and O.

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

Scala 3, 145 bytes

Golfed version. Attempt This Online!

(w,s)=>s.map(c=>(w+" "+w.split(" ").map(_.capitalize).mkString(" ")).split(" ").map(x=>x(0).toInt->x).toMap.getOrElse(c.toInt,c+"")).mkString("")

Ungolfed version. Attempt This Online!

object Main {
  def f(w: String, s: String): String = {
    // Create a translation map
    val translationMap = (w + " " + w.split(" ").map(_.capitalize).mkString(" "))
      .split(" ")
      .map(word => word.head.toInt -> word)
      .toMap

    // Translate the string s using the created map
    val translatedString = s.map(c => translationMap.getOrElse(c.toInt, c.toString)).mkString("")

    translatedString
  }

  def main(args: Array[String]): Unit = {
    val result = f("abra cadabra", (32 to 126).map(_.toChar).mkString)
    println(result)
  }
}
\$\endgroup\$
2
\$\begingroup\$

Scala 3, 76 bytes

w=>_.map(c=>c+(w split " "find(_(0)==c.toLower)getOrElse "a").tail).mkString

Attempt This Online!

Based on this answer by 138 Aspen. Might be further golfable but I need to run now

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

Perl 5 + -p, 36 bytes

%a=<>=~/(\S)(\S*)/g;s/./$&$a{lc$&}/g

Try it online!

Explanation

The hash %a is built using the first letter of each segment (from <>, STDIN) as the key and any remaining letters (0 or more) as the value. Then s///ubstitution is performed on $_ replacing each character in the string with itself ($&) followed by the value from the hash at (the lowercase) key in %a. $_ is then implicitly -printed.

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

Julia, 72 68 bytes

w%s=prod(c->"$c"join((W=w|>split)[find(t->t[1]==c|' ',W)])[2:end],s)

Try it online!

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

CJam, 19 bytes

lq\S/_32af.^+_:c\er

Test it here.

Explanation

l       e# Read first line of input (list of words).
q\      e# Read remaining input and swap with first line.
S/      e# Split around spaces.
_       e# Duplicate.
32af.^  e# Convert the first letter of each word to upper case by taking
        e# the element-wise XOR with the list [32].
+       e# Append the upper-cased words to the original ones.
_:c     e# Duplicate and convert each word to its first character.
\       e# Swap characters with words.
er      e# Transliteration, replacing each character with the corresponding word.
\$\endgroup\$
1
\$\begingroup\$

Uiua, 38 bytes

Try it online!

/◇⊂⨬⋅∘(⊡⊙◌)⊸⊃∈(⊗:)⊙:⊙¤⊸≡◇⊢⊂⊸⍚⍜⊢⌵⊜□⊸≠@ 

This can probably be golfed more, but it's proving tough.

Explanation

                                ⊜□⊸≠@  # split at spaces
                          ⊂⊸⍚⍜⊢⌵ # join capitalized version
                      ⊸≡◇⊢ # get all first letters
           ⊸⊃∈(⊗:)⊙:⊙¤ # make mask of substitution positions a
                       # and indices of the replacements
   ⨬⋅∘(⊡⊙◌) # substitute character with replacement
/◇⊂ # join into final string
\$\endgroup\$
0
\$\begingroup\$

Ruby, 65 60 58 bytes

->w,s{s.gsub(/\w/){|c|w=~/\b#{c}(\w+)/i;c+($1||c)[1..-1]}}

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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