38
\$\begingroup\$

This is a byte sized challenge where you have to convert an input temperature in one of the three units (Celsius, Kelvin and Fahrenheit) to the other two.

Input

You would be provided with a temperature as a number followed by a unit (separated by space). The temperature can be an integer or a floating point number (23 vs 23.0 or 23.678).

You can submit a function or a full program that reads the space separated string from STDIN/ARGV/function argument or the closest equivalent and prints the output to STDOUT or closest equivalent.

Output

Your output should be the temperature converted to the other two formats, separated by a newline and followed by the corresponding unit character on each line (optionally separated by a space). The order of the two units does not matter.

Output precision

  • The converted number should be accurate to at least 4 decimal places without rounding.
  • Trailing zeroes or decimal places are optional as long as first 4 decimal places (without rounding) are precise. You can also skip the 4 zeroes and/or the decimal point in case the actual answer has 4 zeroes after the decimal point.
  • There should not be any leading zeroes
  • Any number format is acceptable as long as it fulfills the above three requirements.

Unit representation

Unit of temperature can only be one of the following:

  • C for Celsius
  • K for Kelvin
  • F for Fahrenheit

Examples

Input:

23 C

Output:

73.4 F
296.15 K

Input:

86.987 F

Output:

303.6983 K
30.5483 C

Input:

56.99999999 K

Output:

-216.1500 C
-357.0700 F

This is so shortest entry in bytes wins! Happy Golfing!

Leaderboard

<script>site = 'meta.codegolf',postID = 5314,isAnswer = true,QUESTION_ID = 50740</script><script src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js'></script><script>jQuery(function(){var u='https://api.stackexchange.com/2.2/';if(isAnswer)u+='answers/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJeRCD';else u+='questions/'+postID+'?order=asc&sort=creation&site='+site+'&filter=!GeEyUcJFJO6t)';jQuery.get(u,function(b){function d(s){return jQuery('<textarea>').html(s).text()};function r(l){return new RegExp('<pre class="snippet-code-'+l+'\\b[^>]*><code>([\\s\\S]*?)<\\/code><\/pre>')};b=b.items[0].body;var j=r('js').exec(b),c=r('css').exec(b),h=r('html').exec(b);if(c!==null)jQuery('head').append(jQuery('<style>').text(d(c[1])));if (h!==null)jQuery('body').append(d(h[1]));if(j!==null)jQuery('body').append(jQuery('<script>').text(d(j[1])))})})</script>

\$\endgroup\$
  • \$\begingroup\$ I assume the outputs can be in any order. Is it acceptable for all three formats to be output, for example 23C\n73.4F\n296.15K ? or must the input format be supressed? \$\endgroup\$ – Level River St May 25 '15 at 13:48
  • \$\begingroup\$ @steveverrill the order bit is mentioned in the output section. You have to only output the other two formats. \$\endgroup\$ – Optimizer May 25 '15 at 13:49
  • \$\begingroup\$ About output precision: 2/3 => 0.666666666666 is accurate to the 4th digits? (I'd say YES). Or should it be 0.6667? \$\endgroup\$ – edc65 May 25 '15 at 13:52
  • \$\begingroup\$ @edc65 0.666666666666 is correct. I am enforcing a no-rounding based precision. so 0.6666 is the alternative. \$\endgroup\$ – Optimizer May 25 '15 at 13:54
  • 1
    \$\begingroup\$ @Dennis in the output, there is no rule to print the space or not. But it will be present in the input. \$\endgroup\$ – Optimizer May 27 '15 at 14:35

15 Answers 15

13
\$\begingroup\$

CJam, 77 65 60 59 55 54 52 bytes

l~2|"459.67+1.8/'K 273.15-'C 1.8*32+'F"S/m<{~N2$}%6<

Try it online in the CJam interpreter.

How it works

l~    e# Read and evaluate the input: F, K, C -> 15, 20, 12
2|    e# Bitwise OR with 2: F, K, C -> 15, 22, 14 = 0, 1, 2 (mod 3)

"459.67+1.8/'K 273.15-'C 1.8*32+'F"S/

      e# Push ["459.67+1.8/K" "273.15-C" "1.8*32+F"].
      e# These commands convert from F to K, K to C and C to F.

m<    e# Rotate the array of commands by 15, 22 or 14 units to the left.
{     e# For each command:
  ~   e#     Execute it.
  N   e#     Push a linefeed.
  2$  e#     Copy the temperature for the next iteration.
}%    e# Collect all results in an array.
6<    e# Keep only the first 8 elements.
\$\endgroup\$
32
\$\begingroup\$

Python 3, 118 116 bytes

I=input()
t=eval(I[:-1])
u=ord(I[-1])%7
exec("u=-~u%3;t=[t*1.8-459.67,(t-32)/1.8,t+273.15][u];print(t,'FCK'[u]);"*2)

Performs the conversions in a rotary order K -> F -> C -> K twice.

\$\endgroup\$
  • 43
    \$\begingroup\$ Gotta love 'FCK'[u]. \$\endgroup\$ – Alex A. May 25 '15 at 17:42
  • 11
    \$\begingroup\$ Haha what the heck, guys. Upvote the question and answers, not my dumb comment. :P \$\endgroup\$ – Alex A. May 26 '15 at 17:10
10
\$\begingroup\$

JavaScript (ES6), 127 130 132 bytes

Waiting for some amazing esolanguage answer, I did not find much to golf here.

Using template string, the 3 newlines are significant and counted.

Run snippet in Firefox to test.

F=x=>([t,u]=x.split(' '),z=273.15,y=9/5,u<'F'?`${t*y+32} F
${+t+z} K`:u<'K'?`${t=(t-32)/y} C
${t+z} K`:`${t-=z} C
${t*y+32} F`)

// Predefined tests

;['23 C','86.987 F','56.99999999 K']
.forEach(v=>O.innerHTML += v+' ->\n'+F(v)+'\n\n')
<input id=I><button onclick='O.innerHTML=F(I.value)'>-></button><br>
<pre id=O></pre>

\$\endgroup\$
7
\$\begingroup\$

Pip, 58 57 bytes

Ft"CFK"RMbP(a-(o:[32i273.15]Ab%7))*$/95@A[tb]+(oAt%7).s.t

Takes input from command-line arguments.

Formatted and slightly ungolfed:

o:[32 0 273.15]
F t ("CFK" RM b)
  P (a - o@(Ab % 7))
    * "95"@At / "95"@Ab
    + o@(At%7)
    . s . t

Explanation:

The general conversion formula between unit 1 and unit 2 is temp2 = (temp1 - offset1) * mult2 / mult1 + offset2. The offsets could be to absolute zero or to any other convenient temperature; let's use 0 °C.

Unit Mult Offset
C    5    0     
K    5    273.15
F    9    32    

We'll build lists of these values and index into them based on which unit we're dealing with. Pip doesn't have associative arrays/hashes/dictionaries, so we need to convert the characters into integer indices. Maybe there will be helpful patterns with the ASCII values.

Unit Asc A%2 Mult A%7 A%7%3 Offset
C    67  1   5    4   1     0
K    75  1   5    5   2     273.15
F    70  0   9    0   0     32

This looks promising. One more useful fact: indices in Pip wrap around. So we don't actually need the %3 as long as we're indexing into something of length 3. Defining o:[32 0 273.15] and using (o (Ab)%7) will do the trick. (A gets the ASCII value of a character. The (l i) syntax is used for indexing into iterables, as well as for function calls.)

For the multipliers, we only need the two numbers 9 and 5. Since numbers are the same as strings in Pip, and thus are indexable, getting the multiplier is as simple as 95@Ab (using the other method of indexing, the @ operator).

Using Pip's array-programming features, we can save a character over the naive method:

95@At/95@Ab
$/95@A[tb]    Make a list of t and b, apply 95@A(...) to each item, and fold on /

Finally, add the offset for the new unit, concatenate a space and the new unit's symbol onto the end, and print.

We do this for each t in "CFK" RM b, thus converting to each unit except the original.

Sample invocation:

C:\Golf> pip.py tempConv.pip 86.987 F
30.548333333333332 C
303.6983333333333 K

(For more on Pip, see the repository.)

\$\endgroup\$
6
\$\begingroup\$

dc, 102 bytes

I'm pretty sure this can be golfed more, but here's a start:

4k[9*5/32+dn[ F
]n]sf[459.67+5*9/dn[ K
]n]sk[273.15-1/dn[ C
]n]sc[rlfxlkxq]sC[lkxlcxq]sF?dC=CF=Flcxlfx

dc barely makes the grade on this one. Specifically dc string handling isn't really up to the job. But all we need to do is differentiate between "C", "F" and "K". Fortunately dc parses "C" and "F" as hex numerals 12 and 15. And fo "K" it just leaves 0 on the stack.

Output:

$ dc -f tempconv.dc <<< "23 C"
73.4000 F
296.1500 K
$ dc -f tempconv.dc <<< "86.987 F"
303.6983 K
30.5483 C
$ dc -f tempconv.dc <<< "56.99999999 K"
-216.1500 C
-357.0700 F
$
\$\endgroup\$
5
\$\begingroup\$

C, 160 bytes

float v,f[]={1,1.8,1},d[]={0,32,273.15};u,t,j;main(){scanf("%f %c",&v,&u);for(u=u/5-13,v=(v-d[u])/f[u];j<2;)t=(++j+u)%3,printf("%f %c\n",f[t]*v+d[t],"CFK"[t]);}

This reads from stdin. No output precision is specified, so it prints whatever printf() feels like printing, which is mostly more than 4 digits.

Ungolfed version:

#include <stdio.h>

float v, f[] = {1.0f, 1.8f, 1.0f}, d[] = {0.0f, 32.0f, 273.15f};
char u;
int t, j;

int main() {
    scanf("%f %c", &v, &u);
    u = u / 5 - 13;
    v = (v - d[u]) / f[u];
    for( ; j < 2; ) {
        t = (++j + u) % 3;
        printf("%f %c\n", f[t] * v + d[t], "CFK"[t]);
    }

    return 0;
}

Some explanations/remarks:

  • This is based on lookup tables f and d that contains the multiplication factors and offsets to convert Celsius to any other unit (including Celsius itself, to avoid special cases).
  • If u is the input unit, u / 5 - 13 maps C to 0, F to 1, and K to 2.
  • Input is always converted to Celsius.
  • Loop iterates over the two units that are not the input, and converts the Celsius value to that unit.
  • The golfed version uses an int variable instead of a char variable to receive the scanf() input. This is a type mismatch, which will only produce correct results on little endian machines (which is almost all of them these days).
\$\endgroup\$
  • \$\begingroup\$ Shortened to 152: float v,f[]={1,1.8,1,0,32,273.15};u;main(j){scanf("%f %c",&v,&u);for(u=u/4&3,v-=f[u+3],v/=f[u];j++<3;printf("%f %c\n",f[u]*v+f[u+3],"CFK"[u]))u++,u%=3;}. Gained a bit with fewer variables, moving code around. New assumption is argc=1 (j=1). u = u/4 & 3. \$\endgroup\$ – domen May 27 '15 at 13:25
4
\$\begingroup\$

Python 2, 168 Bytes

I saw the Python 3 solution just as I was about to post this, but whatever, I'm just practicing golfing.

s=raw_input().split();v=eval(s[0]);c,t=(v-32)/1.8,v-273.15
print[["%fC\n%fF"%(t,t*1.8+32),"%fK\n%fC"%(c+273.15,c)][s[1]=="F"],"%fK\n%fF"%(v+273.15,v*1.8+32)][s[1]=="C"]

Ungolfed:

def conv(s):
    s = s.split()
    v = float(s[0])
    if s[1]=="C":
        print "%f K\n%f F"%(v+273.15,v*1.8+32)
    elif s[1]=="F":
        v = (v-32)/1.8
        print "%f K\n%f C"%(v+274.15,v)
    else:
        c = v-273.15
        print "%f C\n%f F"%(c,c*1.8+32)
\$\endgroup\$
3
\$\begingroup\$

Perl, 85 80 76

#!perl -nl
print$_=/C/?$_+273.15." K":/K/?$_*9/5-459.67." F":5/9*($_-32)." C"for$_,$_

Test me.

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

PHP, 161 153

function f($i){list($v,$u)=split(" ",$i);$u==C||print($v=$u==K?$v-273.15:($v-32)*5/9)."C\n";$u!=K&&print $v+273.15 ."K\n";$u!=F&&print $v*9/5+32 ."F\n";}

http://3v4l.org/CpvG7

Would be nice to golf out two more characters to get in the top ten...

\$\endgroup\$
  • \$\begingroup\$ Well technically, based on the rules, there doesn't need to be spaces between the unit and it's temperature in the output. By my calculation that saves 3 bytes. \$\endgroup\$ – Kade May 27 '15 at 13:43
  • \$\begingroup\$ Good point :-) I also found a way to reuse a variable, which saves another handful. \$\endgroup\$ – Stephen May 27 '15 at 14:45
  • \$\begingroup\$ 135 byte long solution: sandbox.onlinephpfunctions.com/code/…. Basically: removed the \n and changed into real newlines, converted into a full program (receiving the data over GET, eg: http://localhost/my_file.php?t=<temperature>) and replaced $u!=K with $u^K and $u!=F with $u^F. If $u is K, running $u^K will return an empty string, which is a falsy value. Also, your space inside the split was converted into C^c (Just to look cool). \$\endgroup\$ – Ismael Miguel May 27 '15 at 16:13
3
\$\begingroup\$

Python 2, 167

s=raw_input();i=eval(s.split()[0]);d={"C":"%f K\n%f F"%(i+273,32+i*1.8),"K":"%f C\n%f F"%(i-273,i*1.8-459.4),"F":"%f C\n%f K"%(i/1.8-17.78,i/1.8+255.2)};print d[s[-1]]`

This is my first try on CodeGolf.

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG. This is a nice attempt for the very first golf! I have added some sugar to your post by correcting formatting and stuff. \$\endgroup\$ – Optimizer May 27 '15 at 20:11
2
\$\begingroup\$

Pyth, 126 bytes

AYZczdJvY=Y*JK1.8
?%"%f F\n%f K",+32Y+J273.15qZ"C"?%"%f F\n%f C",-Y459.67-J273.15qZ"K"?%"%f C\n%f K",c-J32K*+J459.67c5 9qZ"F"

This feels really long to me...oh well.

\$\endgroup\$
  • 8
    \$\begingroup\$ There's a Python solution shorter than this :P \$\endgroup\$ – orlp May 25 '15 at 21:16
  • \$\begingroup\$ @orlp I know, I know... \$\endgroup\$ – kirbyfan64sos May 25 '15 at 21:17
2
\$\begingroup\$

R, 150 144 141 bytes

a=scan(,"");U=c("C","K","F");i=which(U==a[2]);Z=273.15;x=scan(t=a[1]);cat(paste(c(C<-c(x,x-Z,5*(x-32)/9)[i],C+Z,32+C*9/5)[-i],U[-i]),sep="\n")

Indented, with new lines:

a=scan(,"")
U=c("C","K","F")
i=which(U==a[2])
Z=273.15
x=as.double(a[1])
cat(paste(c(C<-c(x,x-Z,5*(x-32)/9)[i],C+Z,32+C*9/5)[-i],
            U[-i]),
    sep="\n")

Usage:

> a=scan(,"");U=c("C","K","F");i=which(U==a[2]);Z=273.15;x=scan(t=a[1]);cat(paste(c(C<-c(x,x-Z,5*(x-32)/9)[i],C+Z,32+C*9/5)[-i],U[-i]),sep="\n")
1: 23 C
3: 
Read 2 items
Read 1 item
296.15 K
73.4 F
> a=scan(,"");U=c("C","K","F");i=which(U==a[2]);Z=273.15;x=scan(t=a[1]);cat(paste(c(C<-c(x,x-Z,5*(x-32)/9)[i],C+Z,32+C*9/5)[-i],U[-i]),sep="\n")
1: 56.9999999 K
3: 
Read 2 items
Read 1 item
-216.1500001 C
-357.07000018 F
> a=scan(,"");U=c("C","K","F");i=which(U==a[2]);Z=273.15;x=scan(t=a[1]);cat(paste(c(C<-c(x,x-Z,5*(x-32)/9)[i],C+Z,32+C*9/5)[-i],U[-i]),sep="\n")
1: 86.987 F
3: 
Read 2 items
Read 1 item
30.5483333333333 C
303.698333333333 K

Thanks to @AlexA. & @MickyT. !

\$\endgroup\$
  • \$\begingroup\$ Nice work. You can save a byte using as.double() rather than as.numeric(). \$\endgroup\$ – Alex A. May 26 '15 at 17:11
  • \$\begingroup\$ I think the switch statement can be done with c(x,x-273.15,5*(x-32)/9)[i] for 4 characters \$\endgroup\$ – MickyT May 26 '15 at 22:22
  • \$\begingroup\$ Thanks! Actually, prior to version 3.0, I could have shorten it more with as.real() instead of as.numeric(), but the function is defunct now. \$\endgroup\$ – plannapus May 27 '15 at 8:23
  • \$\begingroup\$ Another saving would be replacing as.double(a[1]) with scan(t=a[1]). \$\endgroup\$ – MickyT May 27 '15 at 11:14
2
\$\begingroup\$

Javascript, 206 193 187 175 162 159 156

e=273.15,a=prompt(f=1.8).split(" "),b=+a[0],X=b-32,c=a[1];alert(c=="F"&&(X/f+"C\n"+(X/f+e+"K"))||(c=="C"?b*f+32+"‌​F\n"+(b+e+"K"):b*f-459.67+"F\n"+(b-e+"C")))

Thanks goes to Optimizer and Ismael Miguel for helping me golf it a little further.

\$\endgroup\$
  • 1
    \$\begingroup\$ You can save a few bytes by converting the if else to ?: \$\endgroup\$ – Optimizer May 26 '15 at 17:03
  • 1
    \$\begingroup\$ You could save a few more by combining your if ... return; return ?: to a return ?: ?: \$\endgroup\$ – Daniel May 26 '15 at 18:05
  • 1
    \$\begingroup\$ You can save 1 byte replacing a=prompt().split(" "),e=273.15,f=1.8;alert([...] with a=prompt(e=273.15,f=1.8).split(" "),alert([...]. Also, you can remove the spaces after the unit. Also, removing the return and moving the alert inside the function reduced a lot! And instead of setting a, just use the apply() method with the split. But here you go: (function(b,c){alert(c=="F"&&((b-32)/f+"C\n"+((b-32)/f+e+"K"))||(c=="C"?b*f+32+"F\n"+(b+e+"K"):b*f-459.67+"F\n"+(b-e+"C")))}).apply(e=273.15,prompt(f=1.8).split(" "))! 166 bytes (-21 bytes). Ping me in the chat if you have doubts. \$\endgroup\$ – Ismael Miguel May 27 '15 at 16:48
  • 1
    \$\begingroup\$ I just got it down to 162 anyway. \$\endgroup\$ – SuperJedi224 May 27 '15 at 17:23
  • 1
    \$\begingroup\$ You're right, I missed some of the spaces. Thank you for pointing that out. \$\endgroup\$ – SuperJedi224 May 27 '15 at 17:28
2
\$\begingroup\$

Mathematica, 66

Hopefully correct this time.

Print[1##]&@@@Reduce[F==1.8K-459.67&&C==K-273.15&&#==#2,,#2];&@@#&

Example

%[37 C]   (* % represents the function above *)

310.15 K

98.6 F

\$\endgroup\$
  • \$\begingroup\$ The OP said in a comment that "You have to only output the other two formats." \$\endgroup\$ – lirtosiast May 26 '15 at 22:43
  • \$\begingroup\$ @Thomas That and other problems (hopefully) fixed. Not very good but I am losing interest. \$\endgroup\$ – Mr.Wizard May 26 '15 at 23:00
1
\$\begingroup\$

Excel, 239 bytes

=IF(RIGHT(A1,1)="C",LEFT(A1,LEN(A1)-2)+273.15&"K
"&9*LEFT(A1,LEN(A1)-2)/5+32&"F",IF(RIGHT(A1,1)="K",LEFT(A1,LEN(A1)-2)-273.15&"C
"&(LEFT(A1,LEN(A1)-2)*9/5-459.67&"F",(LEFT(A1,LEN(A1)-2)+459.67)*5/9&"K
"&(LEFT(A1,LEN(A1)-2)-32)*5/9&"C"))

112 bytes of which are used to seperate Value and Unit. Anybody know a better solution?

\$\endgroup\$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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