Code Billiards (Levenshtein golf)

24

1

You must use one language to write programs that perform the following nine tasks, in any order you want.

  • Convert an inputted number from base 10 to base 36.
    • Sample input: 1000
    • Sample output: RS (output must be upper case)
  • Convert each character in a string to its base 10 decimal ASCII codes and print the codes concatenated together.
    • Sample input: Scrambled 3GG5
    • Sample output: 839911497109981081011002051717153
  • Determine if an inputted number is divisible by 1738.
    • Return a truthy value if it is and a falsy value if it isn't.
  • Determine if a string has the letter q in it.
    • Return a truthy value if it does and a falsy value if it doesn't.
  • Encode an inputted string of letters with a Caesar cipher of +1.
    • Case must be preserved. Non-letter characters will be printed without modification.
    • Sample input: Good morning, World!
    • Sample output: Hppe npsojoh, Xpsme!
  • Find and print the sum of the prime factors of a number.
    • Sample input: 1320
    • Sample output: 21
  • Print PPCG.
  • Print the first n positive integers that are divisible by floor(sqrt(n)).
    • n is an inputted integer.
  • Replace every o and O in an inputted string with .
    • Sample input: Onomatopoeia
    • Sample output: ಠnಠmatಠpಠeia

You will have noticed that this challenge is Code Billiards, not Code Golf. The objective of this challenge, like in billiards, is to set up your code so it can be modified only slightly for the next challenge. This is why your programs do not have to solve the above tasks in order.

Your score is determined as follows

  • Your score goes up by 1 each byte in your programs.
  • Your score goes up by floor(n^(1.5)) if two consecutive programs have a Levenshtein distance of n. For example if your first program is potato and your second program is taters, your score goes up by 12 for 12 bytes and by 11=floor(5^(1.5)) for a Levenshtein distance of 5.

The objective of this challenge is to have as low a score as possible after all nine programs have been written. Standard CG rules apply.


To see the leaderboard, click "Show code snippet", scroll to the bottom and click "► Run code snippet". Snippet made by Optimizer.

/* Configuration */

var QUESTION_ID = 63675; // Obtain this from the url
// It will be like http://XYZ.stackexchange.com/questions/QUESTION_ID/... on any question page
var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";
var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk";
var OVERRIDE_USER = 43444; // This should be the user ID of the challenge author.

/* App */

var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page;

function answersUrl(index) {
  return "http://api.stackexchange.com/2.2/questions/" +  QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER;
}

function commentUrl(index, answers) {
  return "http://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER;
}

function getAnswers() {
  jQuery.ajax({
    url: answersUrl(answer_page++),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      answers.push.apply(answers, data.items);
      answers_hash = [];
      answer_ids = [];
      data.items.forEach(function(a) {
        a.comments = [];
        var id = +a.share_link.match(/\d+/);
        answer_ids.push(id);
        answers_hash[id] = a;
      });
      if (!data.has_more) more_answers = false;
      comment_page = 1;
      getComments();
    }
  });
}

function getComments() {
  jQuery.ajax({
    url: commentUrl(comment_page++, answer_ids),
    method: "get",
    dataType: "jsonp",
    crossDomain: true,
    success: function (data) {
      data.items.forEach(function(c) {
        if (c.owner.user_id === OVERRIDE_USER)
          answers_hash[c.post_id].comments.push(c);
      });
      if (data.has_more) getComments();
      else if (more_answers) getAnswers();
      else process();
    }
  });  
}

getAnswers();

var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/;

var OVERRIDE_REG = /^Override\s*header:\s*/i;

function getAuthorName(a) {
  return a.owner.display_name;
}

function process() {
  var valid = [];
  
  answers.forEach(function(a) {
    var body = a.body;
    a.comments.forEach(function(c) {
      if(OVERRIDE_REG.test(c.body))
        body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>';
    });
    
    var match = body.match(SCORE_REG);
    if (match)
      valid.push({
        user: getAuthorName(a),
        size: +match[2],
        language: match[1],
        link: a.share_link,
      });
    else console.log(body);
  });
  
  valid.sort(function (a, b) {
    var aB = a.size,
        bB = b.size;
    return aB - bB
  });

  var languages = {};
  var place = 1;
  var lastSize = null;
  var lastPlace = 1;
  valid.forEach(function (a) {
    if (a.size != lastSize)
      lastPlace = place;
    lastSize = a.size;
    ++place;
    
    var answer = jQuery("#answer-template").html();
    answer = answer.replace("{{PLACE}}", lastPlace + ".")
                   .replace("{{NAME}}", a.user)
                   .replace("{{LANGUAGE}}", a.language)
                   .replace("{{SIZE}}", a.size)
                   .replace("{{LINK}}", a.link);
    answer = jQuery(answer);
    jQuery("#answers").append(answer);

    var lang = a.language;
    lang = jQuery('<a>'+lang+'</a>').text();
    
    languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang, user: a.user, size: a.size, link: a.link};
  });

  var langs = [];
  for (var lang in languages)
    if (languages.hasOwnProperty(lang))
      langs.push(languages[lang]);

  langs.sort(function (a, b) {
    if (a.lang_raw.toLowerCase() > b.lang_raw.toLowerCase()) return 1;
    if (a.lang_raw.toLowerCase() < b.lang_raw.toLowerCase()) return -1;
    return 0;
  });

  for (var i = 0; i < langs.length; ++i)
  {
    var language = jQuery("#language-template").html();
    var lang = langs[i];
    language = language.replace("{{LANGUAGE}}", lang.lang)
                       .replace("{{NAME}}", lang.user)
                       .replace("{{SIZE}}", lang.size)
                       .replace("{{LINK}}", lang.link);
    language = jQuery(language);
    jQuery("#languages").append(language);
  }

}
body { text-align: left !important}

#answer-list {
  padding: 10px;
  width: 290px;
  float: left;
}

#language-list {
  padding: 10px;
  width: 290px;
  float: left;
}

table thead {
  font-weight: bold;
}

table td {
  padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b">
<div id="language-list">
  <h2>Shortest Solution by Language</h2>
  <table class="language-list">
    <thead>
      <tr><td>Language</td><td>User</td><td>Score</td></tr>
    </thead>
    <tbody id="languages">

    </tbody>
  </table>
</div>
<div id="answer-list">
  <h2>Leaderboard</h2>
  <table class="answer-list">
    <thead>
      <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr>
    </thead>
    <tbody id="answers">

    </tbody>
  </table>
</div>
<table style="display: none">
  <tbody id="answer-template">
    <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>
<table style="display: none">
  <tbody id="language-template">
    <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr>
  </tbody>
</table>

Arcturus

Posted 2015-11-12T16:31:43.640

Reputation: 6 537

1Whoa... I literally had the EXACT same idea for a challenge last night. How weird... – ETHproductions – 2015-11-12T17:21:47.043

@ETHproductions I got the idea last night as well, and wrote something about it on the Sandbox. Did your idea come from there? If not, the coincidence is really funny. – Arcturus – 2015-11-12T17:27:51.323

1No, I had the idea as I was on my way to bed. Didn't see your post at all! I guess this is an example of "code-golf minds think alike" ;) – ETHproductions – 2015-11-12T17:29:16.943

What's the Levenshtein-distance of and a? Is it 1 (counting as 1 char) or 2 (because is actually 2 bytes)? – Jakube – 2015-11-13T14:26:32.073

What's the Caesar-Chiphre of "zZ"?. Is it "aA" or "Aa"? – Jakube – 2015-11-13T14:34:22.777

@Jakube Aa. Capitalization is held constant. Since it is a substitution, the distance is 1. – Arcturus – 2015-11-13T15:49:25.200

So which is it? Aa has the inverse capitalization of zZ. – Lynn – 2015-11-13T17:12:55.613

@Mego Well, it's kind of slow. – SuperJedi224 – 2015-11-13T20:13:14.197

1

@Mego Here's a faster algorithm. :) Also, you may not have seen this, but in my answer is a snippet that automatically arranges the programs in the optimal order, and it uses the super-fast algorithm, too.

– ETHproductions – 2015-11-14T05:13:22.163

Answers

8

Japt, 886 866 766 725 688 669

Tasks 5 and 6 are killers. Perhaps there are shorter ways to get them done. I think the Levenshtein distances could still be reduced as well.

  • Task 3 (divisiblity): !(U%#ۊ
    7 bytes (arabic char messes up alignment)
  • Task 4 ('q' check): U!=Uk'q 7 bytes, dist 11
  • Task 1 (base conversion): Us36 u 6 bytes, dist 14
  • Task 2 (ASCII codes): UmX=>Xc 7 bytes, dist 14
  • Task 7 (see for yourself): "PPCG" 6 bytes, dist 18
  • Task 9 (ಠ replacement): Ur"[Oo]",'ಠ 13 bytes, dist 27
  • Task 8 (floor(sqrt(n))): X=Uq f;XoU*X+1,X 16 bytes, dist 52
  • Task 6 (prime factor sum): 2oU fX=>2oX eY=>X%Y &&!(U%X)r(X,Y =>X+Y 39 bytes, dist 172
  • Task 5 (Caesar cipher): UmX=>128o mY=>Yd)a k'A i#Z,'A k'a i#z,'a gXc 44 bytes, dist 216

Here's a snippet that will tell you (one of) the most efficient ways to arrange your programs:

function L(s,t) {
  if(s == t) return 0;
  if(s.length === 0) return t.length;
  if(t.length === 0) return s.length;
  
  var v0 = Array(t.length+1),
      v1 = Array(t.length+1);
  
  for(var i=0; i<v0.length; i++) v0[i]=i;
  for(i=0; i<s.length; i++) {
    v1[0]=i+1;
    for(var j=0; j<t.length; j++)
      v1[j+1] = Math.min(v1[j]+1, v0[j+1]+1, v0[j]+(s[i]==t[j]?0:1));
    for(j=0; j<v0.length; j++) v0[j]=v1[j];
  }
  return v1[t.length];
}

function run(x) {
  R.innerHTML='';
  var b={}, k=0, min=1/0, item='';
  for(var i in x) {
    for(var j in x.slice(+i+1)) {
      k=b[i+(+i+(+j)+1)]=b[(+i+(+j)+1)+i]=L(x[+i],x[+i+(+j)+1]);
      if(k<min) min=k, item=i+(+i+(+j)+1);
    }
  }
  var order=item, q=10;
  while(order.length < x.length && q--) {
    min=1/0, item='';
    for(i in b) {
      if(b[i]<min) {
        if(i[0]==order.slice(-1) && order.indexOf(i[1])==-1)
          min = b[i], item = i[1];
      }
    }
    order+=item;
  }
  var score=0,y=0;
  function getByteCount(s){return(new Blob([s],{encoding:"UTF-8",type:"text/plain;charset=UTF-8"})).size}
  console.log("Task",(+order[0]+1)+":",y=getByteCount(x[order[0]])),score+=y
  for(i in order.slice(1))
    console.log(" ",y=Math.pow(b[order[i]+order[+i+1]],1.5)|0),score+=y,
    console.log("Task",(+order[+i+1]+1)+":",y=getByteCount(x[order[+i+1]])),score+=y;
  console.log("Total:",score)
}

console.log = function(){R.innerHTML+=Array.prototype.slice.call(arguments).join(' ');R.innerHTML+='<br>'};
<p>Input programs here, one per line:</p>
<textarea id=O rows="9" style="width:90%"></textarea><br>
<button onclick="run(O.value.split('\n'))">Run</button>
<p id=R></p>

With the latest version of Japt (non-competing in this challenge), most tasks get shorter:

  • Task 1: s36 u 5 bytes
  • Task 2: mc 2 bytes
  • Task 3: v#ۊ
    4 bytes
  • Task 4: oq 2 bytes
  • Task 5: ;B±B+C²UrF,@Bg1+BbX 19 bytes
  • Task 6: k â x 5 bytes
  • Task 7: "PPCG 5 bytes
  • Task 8: B=U¬f)oU*B+1B 13 bytes
  • Task 9: ro'ಠ'i 6 bytes

The optimal order is now 2,4,3,1,6,7,9,8,5, coming in at a whopping score of 217, less than one-third of the original!

Suggestions welcome!

ETHproductions

Posted 2015-11-12T16:31:43.640

Reputation: 47 880

7

Pyth, score 489

Base conversion: 15

s@L+s`MTrG1jQ36

Caesar Cipher: 13 + 11^1.5

u.rGHrBG1z 36

Divisible by 1738: 7 + 11^1.5

!%Q1738

First N positive integers: 8 + 8^1.5

*Rs@Q2SQ

Sum of prime factors: 4 + 6^1.5

s{PQ

Appearance of q in string: 4 + 4^1.5

}\qz

Join all ASCII codes: 5 + 4^1.5

jkCMz

Print "PPCG": 5 + 5^1.5

"PPCG

Replace with : 9 + 7^1.5

Xz"oO"\ಠ

Jakube

Posted 2015-11-12T16:31:43.640

Reputation: 21 462

3

Java, score 8331

Them levenshtein distances are killing my score here.

(These programs take input as command line arguments)

Program 1 (119):

class L{public static void main(String[]a){System.out.print(Integer.toString(Integer.parseInt(a[0]),36).toUpperCase());}}

Program 2 (120+561.5=539):

class L{public static void main(String[]a){/*System.out.print*/for(char b:a[0].toCharArray())System.out.print((int)b);}}

Program 3 (101+491.5=444):

class L{public static void main(String[]a){System.out.print/*for*/(Integer.parseInt(a[0])%1738==0);}}

Program 4 (108+201.5=197):

class L{public static void main(String[]a){System.out.print(/*forInteger.parseInt(*/a[0].indexOf('q')>=0);}}

Program 5 (186+1071.5=1293):

class L{public static void main(String[]a){for(char b:a[0].toCharArray())System.out.print(Character.isLetter(b)?Character.isUpperCase(b)?b>'Y'?'A':(char)(b+1):b>'y'?'a':(char)(b+1):b);}}

Program 6 (327+2281.5=3747):

class L{public static void main(String[]a){int i,k=0,j=i=Integer.parseInt(a[0]);for(;i>0;i--)if(p(i)&&j%i==0)k+=i;System.out.print(k);}static boolean p(int n){if(n<2)return 0>0;if(n==2||n==3)return 1>0;if(n%2==0||n%3==0)return 0>0;int i,k=(int)Math.sqrt(n)+1;for(i=6;i<=k;i+=6)if(n%(i-1)==0||n%(i+1)==0)return 0>0;return 1>0;}}

Program 7 (336+101.5=368)

class L{public static void main(String[]a){/*int i,k=0,j=i=Integer.parseInt(a[0]);for(;i>0;i--)if(p(i)&&j%i==0)k+=i;*/System.out.print("PPCG");}static boolean p(int n){if(n<2)return 0>0;if(n==2||n==3)return 1>0;if(n%2==0||n%3==0)return 0>0;int i,k=(int)Math.sqrt(n)+1;for(i=6;i<=k;i+=6)if(n%(i-1)==0||n%(i+1)==0)return 0>0;return 1>0;}}

Program 8 (351+341.5=549):

class L{public static void main(String[]a){int i,k=1,j=(int)Math.sqrt(i=Integer.parseInt(a[0]));for(;k<i;k++)/*if(p(i)&&j%i==0)k+=i;*/System.out.println(j*k);}static boolean p(int n){if(n<2)return 0>0;if(n==2||n==3)return 1>0;if(n%2==0||n%3==0)return 0>0;int i,k=(int)Math.sqrt(n)+1;for(i=6;i<=k;i+=6)if(n%(i-1)==0||n%(i+1)==0)return 0>0;return 1>0;}}

Program 9 (305+841.5=1075):

class L{public static void main(String[]a){int i,k=1,j=0;System.out.print(a[0].replaceAll("o|O",""+(char)3232));}static boolean p(int n){if(n<2)return 0>0;if(n==2||n==3)return 1>0;if(n%2==0||n%3==0)return 0>0;int i,k=(int)Math.sqrt(n)+1;for(i=6;i<=k;i+=6)if(n%(i-1)==0||n%(i+1)==0)return 0>0;return 1>0;}}

SuperJedi224

Posted 2015-11-12T16:31:43.640

Reputation: 11 342

3It's Java. You shouldn't expect a short score... ;) – kirbyfan64sos – 2015-11-13T18:52:27.893

interface l{static void main(String... – Rohan Jhunjhunwala – 2017-03-20T01:02:54.577

3

Ruby, 1488

Probably a lot of room for improvement here. Spent most of the time calculating the score...

Sum of prime factors: 64
require'prime';p gets.to_i.prime_division.reduce(0){|s,a|s+a[0]}
Base 36: 30 + 471.5 = 352
puts gets.to_i.to_s(36).upcase
Divisible by 1738: 22 + 151.5 = 80
puts gets.to_i%1738==0
Print PPCG: 9 + 181.5 = 85
puts:PPCG
Does string contain q?: 10 + 81.5 = 32
p gets[?q]
Replace o: 23 + 161.5 = 87
puts gets.gsub(/o/i,?ಠ)
Ceasar cipher: 32 + 211.5 = 128
puts gets.tr 'A-Za-z','B-ZAb-za'
ASCII codes: 37 + 261.5 = 169
puts gets.chomp.chars.map(&:ord).join
Integers divisible by square root: 72 + 561.5 = 491
puts *(1..1/0.0).lazy.select{|i|i%Math.sqrt(i).floor==0}.take(gets.to_i)

daniero

Posted 2015-11-12T16:31:43.640

Reputation: 17 193

You might get an improvement if you converted your programs to lambdas – Not that Charles – 2015-11-16T17:02:32.813

1

Pyth, score 817

number 1: 24

Jjk+UTrG1VjKvz36=+k@JN;k

number 2: (9 + 161.5 = 73)

Vz=+kCN;k

number 3: (5 + 81.5 = 27)

/QC"ۊ

number 4: (5 + 141.5 = 57)

hxz\q

number 5: (39 + 371.5 = 264)

J+GrG1VzIhxJNKChCNIhxJKpK)EpC-CK26))EpN

number 6: (4 + 391.5 = 247)

s{PQ

number 7: (5 + 41.5 = 13)

"PPCG

number 8: (12 + 121.5 = 53)

VK/@Q2 1*KhN

number 9 (13 + 131.5 = 59)

j\ಠcj\ಠcz\o\O

Not the best, I just started learning pyth today and thought I'd give it a try, number 5 really killed my score, I think I can get a few of them shorter but That will just hurt me more on the distances. Any tips from more experienced pyth users are appreciated.

Phyxie

Posted 2015-11-12T16:31:43.640

Reputation: 21

Number 6 is what really killed my score. Well, numbers 5, 6, and 9. – SuperJedi224 – 2015-11-13T00:50:00.463

@SuperJedi224 You can change the order of the programs. For example, switching 5 and 7 here would lower the score a bit. – Arcturus – 2015-11-13T04:10:50.470

@Eridan Wait, you can do that? I guess I'll do that this afternoon. – SuperJedi224 – 2015-11-13T12:18:10.883

@SuperJedi224 You must use one language to write programs that perform the following nine tasks, in any order. Good luck! – Arcturus – 2015-11-13T12:32:54.743

35 + 14^1.5 is not 19 – Jakube – 2015-11-13T13:12:29.107

Nice work! I believe the Arabic char and ಠ count as 2 bytes each. Also, surely Pyth has a built-in for base conversion? – ETHproductions – 2015-11-13T13:34:26.907

The 'j' function can convert to a given base but it returns an array of digits. For example jT2 will convert the number 10 to base 2, but it returns [1, 0, 1, 0] and for higher than base 10 conversions it will just return base10 values for each digit so j1000 36 returns [27, 28] rather than [R, S] – Phyxie – 2015-11-13T19:59:14.520

-1

Python 3 (currently invalid), 621 bytes

from numpy import base_repr
import math
print(base_repr(int(input()),36))
print("".join([str(ord(c)) for c in input()]))
if int(input())%1738 == 0:print(True)
else:print(False)
if "q" in input().lower():print(True)
else:print(False)
t=bytes.maketrans(b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",b"bcdefghijklmnopqrstuvwxyzaBCDEFGHIJKLMNOPQRSTUVWXYZA")
print(input().encode("utf-8").translate(t).decode("utf-8"))
print("PPCG")
n=int(input())
for i in range(1,n):
    if i%math.floor(i**0.5)==0:print(i,end=" ")
print("")
y=input()
z=""
for i in y:
    if i.lower()=="o":z+="0"
    else:z+=i
print(z)

Not really that good code but somewhat works :D. The sum of prime factors is not working. I always get a different result from your example so I removed it. Also Python does not support the char so instead it replaces the os with 0s

IO INFO:

1st input: int in base 10 | Output: that number in base 36

2nd input: a string | Output: Ascii numbers of the string

3rd input: integer | Output: True or False depending if number is dividible by 1738

4th input: string | Output: T or F depending if the string has "q" in it

5th input: string | Output: Caser Cipher +1 of the string

6th: just prints "PPCG" literally

7th input: int n | Output: first n ints divisible by floor(sqrt(n))

8th input: string | Output: Replaced all os with 0 (not with ಠ because python does not support that character, don't get too mad :) )

Ciprum

Posted 2015-11-12T16:31:43.640

Reputation: 107

Oh, yeah. Could you please do a basic explanation of calculating prime factors because I always get a different result from the one in your example. – Ciprum – 2015-11-12T19:09:58.833

13Welcome to Programming Puzzles and Code Golf! This doesn't quite meet the requirements of the challenge since the challenge is requesting a different program for each task. Additionally, you'll need to follow the scoring rules for this challenge, particularly noting the Levenshtein distance function. – AdmBorkBork – 2015-11-12T19:18:36.290

3Python does support ಠ, just put a u in front of the string. u"ಠ_ಠ" <- like this – DJgamer98 – 2015-11-13T15:55:34.773