9-hole mini-golf: Text Manipulation

26

4

9-hole mini-golf: Description

  • 9 (mostly fairly easy) code golfing challenges of varying difficulty
  • Penalties for using the same language more than once
  • All challenges about a specific theme (this theme: Text Manipulation)
  • Input and output can be anywhere reasonable (i.e. STDIN and STDOUT, reading from/writing to a file, function argument and return value, etc.) but must NOT be hardcoded into the program
  • Heavily inspired by 9 Hole Challenge and Text Mechanic

Holes

  1. Code-golf bag

    Take two strings as input.
    Output the first string's character count, while ignoring any occurence of any character in the second string.
    Example: f("foobarbaz", "ao") => 5
  2. A pre-text for golfing

    Take two strings as input.
    Output the first string, with every line prefixed with the second.
    Example: f("foo\nbar\nbaz", "a") => "a foo\na bar\na baz"
  3. War of tabs vs spaces

    Take a string s, a number n, and a boolean b (specified however you want) as input.
    If b is true, output s with every tab converted to n spaces.
    Else, output the s with every n spaces converted to tabs.
    Example: f("if (x) {\n\tdoStuff();\n}", 4, true) => "if (x) {\n[sp][sp][sp][sp]doStuff();\n}" ([sp] means space)
  4. Pillars of golf

    Take a string s, a number n, and another number m as input.
    Output s in columns of n lines each and m characters per column.
    Also have padding of one space between the columns.
    Example: f("this is some placeholder text, foo bar baz...", 3, 5) =>

    this  aceho  foo 
    is so lder  bar b
    me pl text, az...
    
  5. Friendly letters

    Take a string s and a number n as input.
    Output the most common group of n letters in s.
    If there is a tie, output any or all of them.
    Example: f("abcdeabcfghiabc", 3) => "abc"
  6. Scrambled eggs letters for breakfast

    Take a string as input.
    Output the string with all of its words scrambled (letter order randomized) except their first and last letters.
    For simplicity, assume that the input will be a list of "word"s, space separated (i.e. in @$&_():;" foo bar, @$&_():;" is considered a "word.")
    Example: f("this is a sentence that will be scrambled") => "tihs is a stcneene that wlil be sclamrbed"
  7. ASCIIfy

    Take a string as input.
    If the string only contains numbers and spaces, then replace the numbers with their respective ASCII characters (removing the spaces).
    Else, do the reverse (characters to numbers).
    Example: f("ASCIIfy challenge") => "65 83 67 73 73 102 121 32 99 104 97 108 108 101 110 103 101"
    Example 2: f("65 83 67 73 73 102 121 32 99 104 97 108 108 101 110 103 101") => "ASCIIfy challenge"
  8. Mini-mini-markdown transformation

    Take a string as input.
    Output the string converted with mini-markdown, as used in comments on Stack Exchange.
    This is an even mini-er version: you only need to handle **bold**, *italics*, and `code`.
    You need not handle invalid nesting, like **foo *bar** baz*. Also assume that when you see a delimiter (* or `), it will always mean to format (i.e. te**st**ing => te<b>st</b>ing, and foo* bar *baz => foo<i> bar </i>baz).
    Example: f("**foo** *bar **baz*** `qux`") => "<b>foo</b> <i>bar <b>baz</b></i> <code>qux</code>"
  9. Only the best characters

    Take a string s, number n, and string r as input.
    Output the nth character of each word in s. (0-indexed, words are space-separated).
    If the length of the word is less than n, use r for that word instead.
    Example: f("this is a test sentence foo bar baz", 2, "-") => "i--snorz"

Scoring

Your score is the sum of the character counts of your programs. For every repeated language, multiply by 110%. For example, if you have three Ruby solutions, and the total character count of all of your solutions is 1000, your score is 1000 * 1.1 * 1.1 = 1210. Round down if you have a non-integer score.

Good luck!

Doorknob

Posted 2014-01-22T22:47:48.857

Reputation: 68 138

Question was closed 2019-11-13T03:53:11.207

1

Challenge 8 touches on one of the least well specified aspects of Markdown, and the one which is hardest to do really well. It needs a clear explanation of how to handle ambiguities and a good test suite. See Emphasis.text from the mdtest suite.

– Peter Taylor – 2014-01-22T22:59:57.013

@PeterTaylor Well, _ doesn't matter since I specified not to include it. I've edited to clarify some of the others. – Doorknob – 2014-01-22T23:04:58.720

What about **foo***bar**baz*? – Peter Taylor – 2014-01-22T23:12:12.890

@PeterTaylor That would be <b>foo</b><i>bar</i><i>baz</i>, as per "Also assume that when you see a delimiter (* or ```), it will always mean to format" – Doorknob – 2014-01-22T23:14:50.623

1

Challenge 6 is identical to this one.

– daniero – 2014-01-23T02:34:26.437

@danerio Darn it! But in mine you don't have to keep the positions of the non-word characters, so it's slightly different. :-P I'll try to make it a little more different... – Doorknob – 2014-01-23T02:37:24.910

:P Also, in challenge 4, the example would suggest that you mean "m characters per column"..? – daniero – 2014-01-23T02:56:25.970

@daniero Yep, fixed. And sorry about the typo of your username in my last comment, just noticed that also :-P – Doorknob – 2014-01-23T02:57:48.960

In challenge 8, can we assume that the <foo>s always appear at the beginning of a word and that the </foo>s always appear at the end? – Justin – 2014-01-23T06:11:01.637

Considering that this is the second question of the kind, is a new tag appropriate? (maybe something like [tag:multi-challenge]) – Justin – 2014-01-23T07:27:02.657

@Quincunx "Also assume that when you see a delimiter (* or \``), it will always mean to format (i.e.testing=>te<b>st</b>ing`," – Doorknob – 2014-01-23T12:49:42.563

*foo**bar**baz*: <i>foo<b>bar</b>baz</i> or <i>foo</i><i>bar</i><i>baz</i>? – Peter Taylor – 2014-01-23T18:01:46.960

@Peter You don't have to handle edge-cases like that. – Doorknob – 2014-01-23T18:03:17.943

4

I'm voting to close this question as off-topic because it's a multi-part challenge with insufficient interaction between the parts

– pppery – 2019-11-09T01:54:52.320

Answers

12

Score: 382 * 1.12 = 462

Languages prone to change.

1. APL, 8 4

Thanks @marinus for shaving 4 chars off.

f←⍴~

Called with the strings as the left and right arguments, eg.

      'foobarbaz' f 'ao'
5

2. Ruby, 35 31

Thanks @DoorknobofSnow for shaving 4 chars off.

f=->s,r{s.gsub(/(?<=^)/,r+' ')}

3. Python, 48

f=lambda s,n,b:s.replace(*['\t',' '*n][::2*b-1])

4. GolfScript, 20

{@//zip{' '*}%n*}:f;

Assumes that the arguments are on the stack. Test online

5. J, 50

f=:({~[:(i.>./)+/"1@=@(}.~0-1{$))@|:@([$~],1+[:$[)

Called with the string as the left argument and the number as the right, eg.

   'abcdeabcfghiabc' f 3
abc

6. Ruby, 61

f=->s{s.gsub(/(?<!^| )[^ ]+(?!$| )/){[*$&.chars].shuffle*''}}

7. GolfScript, 39 35 34

{[.10,' '*-{{}/]' '*}{~]''+}if}:f;

Again, assumes the argument is on the stack. Test online

8. Perl, 98

sub f{$_=@_[0];s!\*\*(.+?)\*\*!<b>$1</b>!g;s!\*(.+?)\*!<i>$1</i>!g;s!`(.+?)`!<code>$1</code>!g;$_}

9. Haskell, 36

f s n r=[(x++cycle r)!!n|x<-words s]

Volatility

Posted 2014-01-22T22:47:48.857

Reputation: 3 206

The APL can actually be shortened to f←⍴~. – marinus – 2015-08-22T10:17:09.690

@marinus thanks, didn't know you could do that in APL – Volatility – 2015-08-23T02:49:52.100

Great! You can save some chars on the Ruby one by using a proc (f=->s,r{...}) instead of a function. I refuse to upvote until it is complete, though :P – Doorknob – 2014-01-23T00:34:28.507

@DoorknobofSnow ah, thanks. Not that proficient with Ruby :) – Volatility – 2014-01-23T00:41:49.107

Hooray, you're the first one to finish :-D +1 – Doorknob – 2014-01-23T12:48:12.507

I get the impression that all of the functions are supposed to return a string, so for number 4 I think you're going to have to use one character more. – Peter Taylor – 2014-01-23T23:17:55.227

@PeterTaylor fixed :) – Volatility – 2014-01-23T23:26:19.797

4

Python - 697 × 1.19 ≈ 1644

Gee, I sure love lambdas.

Note: 3 and 5 were shamelessly copied from Volatility's answer, as I couldn't find a better alternative. Also, this was done just for fun.

f=lambda a,b:sum([x not in b for x in a])        # 1, 41 chars
f=lambda a,b:b+' '+a.replace('\n','\n'+b+' ')    # 2, 43 chars
f=lambda s,n,b:s.replace(*['\t',' '*n][::b*2-1]) # 3, 47 chars
f=lambda s,n,m:'\n'.join([' '.join([s[x:x+m]for x in range(y*m,len(s),m*n)])for y in range(n)])
                                                 # 4, 94 chars
f=lambda s,n:max([s[x:x+n]for x in range(len(s)+1-n)],key=s.count)
                                                 # 5, 66 chars
import random;f=lambda s:' '.join([''.join(sorted(y,key=lambda*x:random.random()))for y in s.split()])
                                                 # 6, 102 chars
f=lambda s:s.replace(' ','').isdigit()and ''.join(map(chr,map(int,s.split())))or ' '.join(map(str,map(ord,s)))
                                                 # 7, 110 chars
import re;f=lambda s:re.sub('`(.*?)`','<code>\\1</code>',re.sub(r'\*(.*?)\*','<i>\\1</i>',re.sub(r'\*\*(.*?)\*\*','<b>\\1</b>',s)))
                                                 # 8, 128 chars
f=lambda s,n,r:''.join([len(x)>n and x[n]or r for x in s.split()])
                                                 # 9, 66 chars

EDIT: Thanks to Volatility for the tips.

Oberon

Posted 2014-01-22T22:47:48.857

Reputation: 2 881

You can use generator expressions for most of them, which will save you a bunch of characters. Also, for 1. there's no need to use int, since booleans are a subclass of them, and for 7. all([...]) can be shortened to x.replace(' ','').isdigit() – Volatility – 2014-01-23T22:15:38.623

The second answer won't prefix the first line of a. – daniero – 2014-01-24T02:06:26.057

1

Score 513 * 1.15 = 826 

Took quite a beating by the same-language penalty. Solved most of these in Ruby just to finish them as fast as I could. Might change some languages later. Added a small recap/explanation on each answer.

1: Python (46)

f=lambda a,b:len([x for x in a if not x in b])

First, shorter answer in Ruby 2.0 (30) that gives more penalty and higher overall score:

p (gets.chars-gets.chars).size

2: Ruby 1.9+ (37)

Returns each line of s prefixed with t:

f=->s,t{s.split(?\n).map{|x|t+x}*?\n}

3: Ruby 1.9+ (48)

Returns s with tabs replaced by n spaces or vice versa, depending on b:

f=->s,n,b{r=[" "*n,?\t];b||r.reverse!;s.gsub *r}

4: Ruby 1.9+ (95)

Somebody shoot me.

f=->s,n,m{[*s.chars.each_slice(m).map{|w|w*''}.each_slice(s.size/m/n)].transpose.map{|w|w*' '}}

5: Ruby 1.9+ (58)

Returns most common run of n characters in s:

f=->s,n{(a=s.chars.each_slice(n)).max_by{|v|a.count v}*''}

6: J (47)

Scrambles the text somehow; Shamelessly stolen verbatim from marinus:

''[1!:2&4('\w(\w+)\w';,1)({~?~@#)rxapply 1!:1[3

7: Ruby (57+1)

Prints input ASCIIfied or de-ASCIIfied. Run with the -p switch.

~/\d/?gsub(/\d+\s*/){$&.to_i.chr}:gsub(/./){"#{$&.ord} "}

8: Sed (87)

Prints input converted from (mini)markdown to HTML:

s:\*\*([^*]+)\*\*:<b>\1</b>:g;
s:\*([^*]+)\*:<i>\1</i>:g;
s:`([^`]+)`:<code>\1</code>:g

9 Ruby 1.9+ (37)

Returns a string of the nth characters of each first word in s, or r:

f=->s,n,r{s.split.map{|w|w[n]||r}*''}

daniero

Posted 2014-01-22T22:47:48.857

Reputation: 17 193

Wouldn't your 8 output <b>test** **test2</b> for **test** **test2**? – Doorknob – 2014-01-23T14:28:32.647

@DoorknobofSnow yes it would ;) Fixed (sed doesn't have non-greedy repetition). – daniero – 2014-01-23T16:30:21.340

What would it give for **foo *bar* baz**? – Volatility – 2014-01-23T22:19:33.763

@Volatility Oops. I didn't read the question properly, thought there wouldn't be any nesting, but it said no invalid nesting. I'm not sure I'll bother fixing it right now. – daniero – 2014-01-24T02:00:30.387

For 1st ruby code - operator works with enumerator ? – Siva – 2014-01-24T07:33:21.113

@shiva No, but in ruby 2.0 (just fixed that, it said 1.9) chars gives an array. I just explained this on another question on this site something like 2 days ago :D – daniero – 2014-01-24T11:07:11.693

Make that 1 day ago.

– daniero – 2014-01-24T11:17:11.077

1

Work in progress

1. Java - 66

int f(String s,String b){for(char c:b)s=s.replace(b,"");return s;}

2. Java - 64

String f(String i,String r){return i.replaceAll("(?m)^",r+" ");}

3. Python - 58

def f(s,n,b):t=" "*n;a=t,'\t';print s.replace(a[b],a[b^1])

4. Python - 84

def f(s,n,m):
 a=['']*n;c=0
 while s:a[c%n]+=s[:m]+" ";s=s[m:];c+=1
 for i in a:print i

5.

6.

7. Befunge 98 - 9

&,5j3.~@#

8.

9.

Justin

Posted 2014-01-22T22:47:48.857

Reputation: 19 757

At the first hole it should be for(char c:b.toCharArray()) and replace(c+"",""); and return s.length(); (or something like that) to get it work. – bobbel – 2014-03-03T13:03:59.170