17
\$\begingroup\$

I spent all of today at a Super Smash Bros. tournament, and I started thinking about some of the terminology we use when describing sets. These are the three kinds of sets that I see played at tournaments:

  • Best of 3 (Bo3)
    • Three games are played. The winner of the set is the player who won the majority of the games.
    • If a single player wins two games of the set, they are immediately declared the winner, because it would be impossible for the opponent to catch up.
  • Best of 5 (Bo5)
    • Five games are played. The winner of the set is the player who won the majority of the games.
    • If a single player wins three games of the set, they are immediately declared the winner, because it would be impossible for the opponent to catch up.
  • First to 5 (Ft5)
    • Okay, I cheated a bit with my wording earlier. This kind of set isn't part of a tournament, but you'll often see them happening in the venue. This is traditionally the kind of set you'll play if you've challenged another player and money is on the line.
    • It's as simple as it sounds: The players repeatedly play games until one of them has won five, and that player is declared the winner.

Obviously, Bo3 and Bo5 are very similar, differing only in the number of games played. But Ft5 is clearly different... right? Not really! No matter how a Bo3 set goes down, the winner will have won exactly two games. The winner of a Bo5 set will have won exactly 3 games. Why not call them Ft2, or Ft3? The same logic, applied in reverse, will show that Ft5 is exactly the same as Bo9.

The objective of this challenge is to determine the synonym of a set format.

Specification

Your program or function will take a single string from input. The first two characters will be Bo or Ft, and they will be followed by a number. The program/function will output a string with the opposite prefix and a number such that the input and output strings mean the same thing.

Any string beginning with Bo will end in an odd number.

You may assume that the number in the input string will never be greater than 200. You may also assume that you will never receive input for which the correct output would include a number greater than 200. Likewise, the input and correct output numbers will always be greater than 0.

Examples

Bo3 -> Ft2
Ft2 -> Bo3

Bo5 -> Ft3
Ft3 -> Bo5

Bo9 -> Ft5
Ft5 -> Bo9

Bo51 -> Ft26
Ft26 -> Bo51

Bo199 -> Ft100
Ft100 -> Bo199
\$\endgroup\$
  • 2
    \$\begingroup\$ Code golf and melee? We could be friends! Unless you're talking about an inferior SSB \$\endgroup\$ – aks. Aug 16 '15 at 3:46
  • 2
    \$\begingroup\$ @aks. of course melee ;) \$\endgroup\$ – undergroundmonorail Aug 16 '15 at 11:30
  • \$\begingroup\$ frikin meleetists... \$\endgroup\$ – Nacht - Reinstate Monica Aug 18 '15 at 0:48
  • 1
    \$\begingroup\$ @aks. There's nothing wrong with project m ;( \$\endgroup\$ – Cilan Jan 24 '16 at 5:12
  • 1
    \$\begingroup\$ @doorhandle except legally speaking. RIP \$\endgroup\$ – undergroundmonorail Jan 24 '16 at 5:13

18 Answers 18

10
\$\begingroup\$

Pyth, 23 bytes

@,/hKsttz2tyKCp-"BoFt"z

Test suite.

How it works:

First, to find the Bo or Ft, the program filters out the characters in the input from BoFt, with -"BoFt"z.

This is immediately printed with p. p also returns its input. That string is converted to a number interpreting the bytes as base 256. The result is 17007 if the string was Bo, and is 18036 if the string was Ft.

Next, it calculates both possible results, num * 2 - 1 and (num + 1)/2 and puts this in a 2 entry list. Then, the program indexes into that list with the above number, 17007 or 18036. Due to Pyth's modular indexing, this selects the proper number. The result is then printed automatically.

Since p prints with no trailing newline, but the implicit printing does have the trailing newline, the two successive prints come out in exactly the right format.

\$\endgroup\$
13
\$\begingroup\$

Python 2, 59

lambda s:'FBto'[s>'C'::2]+`eval(s[2:]+'/*22+-11'[s>'C'::2])`

In short challenges where functions are allowed, the brevity of lambda usually wins out even when the code must repeat itself due to the inability to assign variables.

We check which case we're in with string comparison s>'C'. Then, get the right prefix with the list slicing trick 'FBto'[s>'C'::2].

To get the number, we must evaluate the characters beyond the second and do either *2+1 or /2-1 to it. We do this by tacking on either of those two expressions as strings, again chosen by list slicing, evaluating the result, and turning that number into a string.

Edit: Saved one char (59):

lambda s:eval("''FBto''++``%%ss/*22+-11``"[s>'C'::2]%s[2:])

Don't even ask...

\$\endgroup\$
  • 2
    \$\begingroup\$ You can assign variables inside lambdas. Example: lambda a:(lambda b:b*b)(a+3). It's not particularly short however. \$\endgroup\$ – orlp Aug 16 '15 at 3:43
8
\$\begingroup\$

C++11 Template Metaprogramming, 305 bytes

Edit: Got another 100 bytes off

Do I get any kind of handicap for my choice of language? :p

#define C wchar_t
#define T };template<C p
#define L C...l>struct
#define X l...>
C a{T,L I{T,C c,L I<p,c,X:I<10*p+c-'0',X{T>struct I<p>{enum E{v=p};T,L S{T,C c,C d,L G:G<p/10,c,d,p%10+'0',X{T,L G<0,p,X{typedef S<p,X t;T,L F{T,L F<p,'o',X:G<(I<0,X::v+1)/2,'F','t'>{T,L F<p,'t',X:G<I<0,X::v*2-1,'B','o'>{};

Examples:

#include <type_traits>
static_assert(I<0,'5'>::v == 5, "fail");
static_assert(I<0,'1','0','5'>::v == 105, "fail");
static_assert(I<0,'5','1'>::v == 51, "fail");
static_assert(std::is_same<typename G<5,'B','o'>::t, S<'B','o','5'>>::value, "fail");
static_assert(std::is_same<typename G<51,'F','t'>::t, S<'F','t','5','1'>>::value, "fail");
static_assert(std::is_same<typename F<'B','o','3'>::t, S<'F','t','2'>>::value, "fail");
static_assert(std::is_same<typename F<'F','t','2'>::t, S<'B','o','3'>>::value, "fail");
static_assert(std::is_same<typename F<'B','o','5'>::t, S<'F','t','3'>>::value, "fail");
static_assert(std::is_same<typename F<'F','t','3'>::t, S<'B','o','5'>>::value, "fail");
static_assert(std::is_same<typename F<'B','o','7'>::t, S<'F','t','4'>>::value, "fail");
static_assert(std::is_same<typename F<'F','t','4'>::t, S<'B','o','7'>>::value, "fail");
static_assert(std::is_same<typename F<'B','o','1','1'>::t, S<'F','t','6'>>::value, "fail");
static_assert(std::is_same<typename F<'F','t','6'>::t, S<'B','o','1','1'>>::value, "fail");
static_assert(std::is_same<typename F<'B','o','1','0','5'>::t, S<'F','t','5','3'>>::value, "fail");
static_assert(std::is_same<typename F<'F','t','5','3'>::t, S<'B','o','1','0','5'>>::value, "fail");
static_assert(std::is_same<typename F<'B','o','1','9','5'>::t, S<'F','t','9','8'>>::value, "fail");
static_assert(std::is_same<typename F<'F','t','9','8'>::t, S<'B','o','1','9','5'>>::value, "fail");
int main() {}
\$\endgroup\$
6
\$\begingroup\$

CJam, 29 bytes

l('B=\1>i"Ft"1$)2/+"Bo"@2*(+?

Try it online

Nothing very elaborate here. Calculating the two possible results, and picking one of the two based on the first letter in the input. Will update if I come up with something better.

Explanation:

l     Get input.
(     Pop off first character.
'B=   Compare with 'B.
\1>   Get rest of input to top of stack, and slice off first character.
i     Convert to integer.
"Ft"  String part of first possible output.
1$    Copy input value to top.
)2/   Increment, and divide by 2.
+     Concatenate with string part.
"Bo"  String part of second possible output.
@     Move input value to top.
2*(   Multiply by 2, and decrement.
+     Concatenate with string part.
?     Ternary to pick one of the two constructed outputs, based on comparison
      of first input character with 'B.
\$\endgroup\$
6
\$\begingroup\$

CJam, 27 bytes

4 27]r.^(_o'B=\(oi_2*(\)2/?

This makes use of the fact that 'B' ^ 'F' == 4 and 'o' ^ 't' == 27.

Try it online in the CJam interpreter.

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

Javascript (ES6), 50 47 chars

Very simple solution: (Thanks to undergroundmonorail for removing one byte!)

x=>(y=x.slice(2),x<'C'?'Ft'+-~y/2:'Bo'+(y*2-1))

Ungolfed:

function(x){
  y = x.slice(2); // everything after the 'Ft' or 'Bo'
  return x<'C' ? 'Ft'+Math.ceil(y/2) : 'Bo'+(y*2-1)
}

For once my answer was only ~2x the length of the best Pyth answer!

\$\endgroup\$
  • \$\begingroup\$ I mentioned this in chat but you should be able to replace y/2+.5 with -~y/2 to save a byte. \$\endgroup\$ – undergroundmonorail Aug 16 '15 at 12:35
  • \$\begingroup\$ @undergroundmonorail Thanks for the tip! BTW, I like this challenge because it's simple compared to most challenges, so my answer turns out much shorter than usual. \$\endgroup\$ – ETHproductions Aug 16 '15 at 12:53
4
\$\begingroup\$

Haskell, 69 bytes

f('B':_:x)="Ft"++show(div(read x)2+1)
f(_:_:x)="Bo"++show(2*read x-1)

Reasonably straight-forward.

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

Pyth - 31 bytes

Pretty simple, uses zip and modular indexing to get the switch. The actual calculation is really easy.

s@C,Jc"FtBo"2,h/Ksttz2tyKhxJ<z2

Test suite.

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

Julia, 63 bytes

x->(y=int(x[3:end]);join([x<"C"?"Ft":"Bo",x<"C"?(y+1)÷2:2y-1]))

Ungolfed:

function f(x::String)
    # Extract the number at the end
    y = int(x[3:end])

    # If x is lexographically less than "C", we have
    # "best of," so we need "first to." Otherwise we
    # need "best of."
    if x < "C"
        join(["Ft", (y+1)÷2])
    else
        join(["Bo", 2y-1])
    end
end
\$\endgroup\$
3
\$\begingroup\$

Matlab, 95 bytes

function f(s)
t='Bo';a=2;b=-1;if s(1)<70
t='Ft';a=.5;b=a;end
[t num2str(str2num(s(3:end))*a+b)]

Examples:

>> f('Ft5')
ans =
Bo9
>> f('Bo51')
ans =
Ft26
\$\endgroup\$
3
\$\begingroup\$

Powershell, 111

The wordiness of PowerShell and required parentheses are its downfall again. Even golfing the .Substring(0,2) to [0..1]-join'' only saves 2 bytes each, and another couple bytes saved with an implied Else thanks to the exit command. Oh well. Good refresher on separating strings.

Code:

$b=($a=$args[0])[0..1]-join'';$c=+($a[2..($a.Length-1)]-join'');if($b-eq"Bo"){"Ft"+($c+1)/2;exit};"Bo"+(2*$c-1)

Usage:

PS C:\Scripts\Golfing> .\ssb_tourney.ps1 Bo199
Ft100

Explanation

$b=($a=$args[0])[0..1]-join''      # Take in the command-line argument as $a, recast as
                                   # array, suck out the first two characters, save as $b
$c=+($a[2..($a.Length-1)]-join'')  # Do a similar trick with the right-hand side of $a,
                                   # re-cast it as an integer with the +
if($b-eq"Bo"){                     # If the first letters are "Bo"
    "Ft"+($c+1)/2                  # Implied write of the answer
    exit
}
"Bo"+(2*$c-1)                      # Implied write of the other answer, only reached if
                                   # the input is "Ft", else we would have hit the exit
\$\endgroup\$
3
\$\begingroup\$

Perl 5, 38 bytes (37 + 1 for -p)

$_=/Bo/?Ft.(.5+$'/2):Bo.(2*s/Ft//r-1)

Usage: save as 54768.pl and run as:

perl -p 54768.pl <<< 'Bo3'
# Ft2

or interactively:

perl -p 54768.pl
Bo199
# Ft100
\$\endgroup\$
  • \$\begingroup\$ -p implies -n. You don't need both. \$\endgroup\$ – Dennis Aug 17 '15 at 16:28
  • \$\begingroup\$ @Dennis, indeed I don't! Thank you! \$\endgroup\$ – Dom Hastings Aug 17 '15 at 16:51
3
\$\begingroup\$

FSharp - 153 143 bytes

let t(s:string)=
 let c=s.[2..]|>Seq.map string|>Seq.reduce(+)|>float
 if s.[0]='B'then sprintf"Ft%.0f"(ceil(c/2.)) else sprintf"Bo%.0f"(c*2.-1.)

Updates

  1. Knocked a few bytes off by switching from pattern matching to a simple if ... then ...
\$\endgroup\$
3
\$\begingroup\$

Ruby, 82 Bytes

x=$*[0]
y=x.match(/..(\d*)/)[1].to_i
x=~/Bo/?(puts"Ft#{y/2+1}"):(puts"Bo#{y*2-1}")

Called with an argument to knock off a few bytes.
First post, suggestions welcome. :)

EDIT: Got rid of 12 bytes by changing up my math. Since the Bo numbers are odd they will always have a decimal after dividing by 2, meaning I can just truncate and add 1 instead of using ceil to round up.

\$\endgroup\$
  • \$\begingroup\$ You can save two bytes by removing the space after puts. \$\endgroup\$ – ProgramFOX Aug 19 '15 at 6:58
  • \$\begingroup\$ @ProgramFOX don't know how I missed those, thank you. also, I somehow managed to mess up the edits but I think it's fixed now, haha. \$\endgroup\$ – HuggableSquare Aug 19 '15 at 7:03
  • \$\begingroup\$ We were editing the post at the same time, which caused an edit conflict. Because you submitted later, your edit overwrote mine. I know, edit conflicts are a bit tricky :P \$\endgroup\$ – ProgramFOX Aug 19 '15 at 7:05
3
\$\begingroup\$

PHP, 85 79 75 Bytes

<?php
$f=$argv[1];$s=substr($f,2);echo strpos($f,Bo)===0?Ft.($s+1)/2:Bo.($s*2-1);


Usage:
Call the script with an argument: php -d error_reporting=0 script.php Bo5

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

Not ridiculously short like the others, but that's my first post:

JS, 143 bytes

f=prompt("","");n=parseInt(f.match(/\d{1,}/));s=0;r=0;if(f.match(/B/)){r=(n+1)/2;s="Ft"+r;}if(f.match(/F/)){r=n*2-1;s="Bo"+r;}alert(f+" : "+s);

Ungolfed Version:

var f = prompt("", "");
var n = parseInt(f.match(/\d{1,}/));
var s = 0;
var r = 0;

if (f.match(/B/)) {
  r = (n + 1)/ 2;
  s = "Ft"+r;
 }
if (f.match(/F/)) {
  r = n * 2 - 1;
  s = "Bo"+r;
 }
alert(f+" : "+s);
\$\endgroup\$
  • 7
    \$\begingroup\$ Welcome to Programming Puzzles and Code golf! There are a couple of ways to shorten your code considerably, so here are a few. 1) Almost all whitespace in JavaScript is unnecessary, 2) you don't need the var keyword, and 3) statements can be separated with a semicolon or a newline, so you don't need both. For more general tips have a look at Tips for golfing in JavaScript. \$\endgroup\$ – NinjaBearMonkey Aug 17 '15 at 19:21
2
\$\begingroup\$

R, 144 bytes

New to code-golfing, R, and this site. So here goes:

a=function(){n=readline();z="Bo";p=(as.numeric(gsub("[^0-9]","",n)));if(grepl(z,n)==TRUE){x="Ft";b=(p+1)/2}else{x="Bo";b=p*2-1};cat(x);cat(b)}
\$\endgroup\$
  • \$\begingroup\$ I don't know R but I bet you could get rid of the whitespace. \$\endgroup\$ – undergroundmonorail Aug 18 '15 at 21:32
  • \$\begingroup\$ @undergroundmonorail you're right, R doesn't really use whitespace. I had just written it like that to make it nicer to look at =P the size of the file without the whitespace is 144 bytes, I wasn't sure which number to put so I put the lowest one I could fit that code into. \$\endgroup\$ – a soft pillow Aug 19 '15 at 2:24
  • \$\begingroup\$ Oh, okay :) For the record, it's generally preferable to post the exact code you used for your score, just to make it as easy as possible to verify, though people often include "ungolfed" versions to make it easier to read. The extent of the ungolfing ranges from adding indentation and newlines, to renaming variables, to abstracting chunks of code into functions and generally making the code cleaner. None of that is required, but it's fine so long as the fully golfed version is there. \$\endgroup\$ – undergroundmonorail Aug 19 '15 at 7:11
1
\$\begingroup\$

C#, 110 bytes

string f(string s){var b=s[0]=='B';var o=s.Remove(0,2);int i=int.Parse(o)/2;return b?"Ft"+(i+1):"Bo"+(4*i-1);}
\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! Please include the exact code you have counted in your answer so people can easily check your score (it appears you've counted the code without the unnecessary whitespace). You can always include an ungolfed/readable version in addition to that. \$\endgroup\$ – Martin Ender Aug 19 '15 at 9:26

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.