Temperature Converter

38

6

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>

Optimizer

Posted 2015-05-25T13:27:14.010

Reputation: 25 836

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? – Level River St – 2015-05-25T13:48:35.357

@steveverrill the order bit is mentioned in the output section. You have to only output the other two formats. – Optimizer – 2015-05-25T13:49:42.637

About output precision: 2/3 => 0.666666666666 is accurate to the 4th digits? (I'd say YES). Or should it be 0.6667? – edc65 – 2015-05-25T13:52:16.540

@edc65 0.666666666666 is correct. I am enforcing a no-rounding based precision. so 0.6666 is the alternative. – Optimizer – 2015-05-25T13:54:15.990

@edc65 infact, if you actually need rounding, 0.66667 is correct as well as rounded for you. – Optimizer – 2015-05-25T13:56:50.547

Another minor point I think it would be useful to specify in the question the formulas to be used. I've checked and it seems the formulas you are using are correct according to modern definitions. The strange thing is that VSMOW ("standard" water of a specific isotopic composition) does not freeze at exactly 0C or boil at exactly 100C. http://en.wikipedia.org/wiki/Celsius

– Level River St – 2015-05-25T13:57:01.507

mmm I dont'get the no-rounding part. 0.6667 is a better approximation than 0.6666 to the actual rational number 2/3. It's not a rounding – edc65 – 2015-05-25T13:58:25.597

@edc65 Better in terms of closeness - yes, but here, I am just bothered about correctness to first 4 decimal places. Keeping that in mind, 0.66667 is an even better approximation, right ? – Optimizer – 2015-05-25T13:59:44.867

@steveverrill Nice point, but I actually want to avoid providing the formulas as well in the question, as then it would be simply "Program this formula" question. Too much spoon feeding. – Optimizer – 2015-05-25T14:05:51.650

No validation of less than absolute zero? – Viktor Mellgren – 2015-05-27T10:30:02.700

One of the answers does not print a space between temperature and unit. The output rules don't seem to require it, but all the examples say otherwise. Could you clarify? – Dennis – 2015-05-27T14:25:42.580

1@Dennis in the output, there is no rule to print the space or not. But it will be present in the input. – Optimizer – 2015-05-27T14:35:48.980

Answers

13

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.

Dennis

Posted 2015-05-25T13:27:14.010

Reputation: 196 637

32

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.

Sp3000

Posted 2015-05-25T13:27:14.010

Reputation: 58 729

43Gotta love 'FCK'[u]. – Alex A. – 2015-05-25T17:42:05.517

11Haha what the heck, guys. Upvote the question and answers, not my dumb comment. :P – Alex A. – 2015-05-26T17:10:19.250

10

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>

edc65

Posted 2015-05-25T13:27:14.010

Reputation: 31 086

7

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.)

DLosc

Posted 2015-05-25T13:27:14.010

Reputation: 21 213

6

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
$

Digital Trauma

Posted 2015-05-25T13:27:14.010

Reputation: 64 644

5

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).

Reto Koradi

Posted 2015-05-25T13:27:14.010

Reputation: 4 870

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. – domen – 2015-05-27T13:25:06.013

4

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)

Kade

Posted 2015-05-25T13:27:14.010

Reputation: 7 463

3

Perl, 85 80 76

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

Test me.

nutki

Posted 2015-05-25T13:27:14.010

Reputation: 3 634

3

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...

Stephen

Posted 2015-05-25T13:27:14.010

Reputation: 201

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. – Kade – 2015-05-27T13:43:49.080

Good point :-) I also found a way to reuse a variable, which saves another handful. – Stephen – 2015-05-27T14:45:01.733

135 byte long solution: http://sandbox.onlinephpfunctions.com/code/303e4c29d9f50e4a5af6e72fff9a39ad7041d454. 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).

– Ismael Miguel – 2015-05-27T16:13:35.513

3

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.

C.L.

Posted 2015-05-25T13:27:14.010

Reputation: 31

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. – Optimizer – 2015-05-27T20:11:51.653

2

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.

kirbyfan64sos

Posted 2015-05-25T13:27:14.010

Reputation: 8 730

8There's a Python solution shorter than this :P – orlp – 2015-05-25T21:16:41.757

@orlp I know, I know... – kirbyfan64sos – 2015-05-25T21:17:16.550

2

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. !

plannapus

Posted 2015-05-25T13:27:14.010

Reputation: 8 610

Nice work. You can save a byte using as.double() rather than as.numeric(). – Alex A. – 2015-05-26T17:11:54.677

I think the switch statement can be done with c(x,x-273.15,5*(x-32)/9)[i] for 4 characters – MickyT – 2015-05-26T22:22:43.563

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. – plannapus – 2015-05-27T08:23:58.693

Another saving would be replacing as.double(a[1]) with scan(t=a[1]). – MickyT – 2015-05-27T11:14:43.047

2

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.

SuperJedi224

Posted 2015-05-25T13:27:14.010

Reputation: 11 342

1You can save a few bytes by converting the if else to ?: – Optimizer – 2015-05-26T17:03:10.390

1You could save a few more by combining your if ... return; return ?: to a return ?: ?: – Daniel – 2015-05-26T18:05:26.770

1You 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. – Ismael Miguel – 2015-05-27T16:48:34.917

@IsmaelMiguel: a[0] needs to be cast to a number, it doesn't work right otherwise. I'll look into the other stuff you suggested though. – SuperJedi224 – 2015-05-27T17:08:39.547

You can add b+=0; inside the function, before the alert. – Ismael Miguel – 2015-05-27T17:15:32.077

That wouldn't work, but I found a solution that does. – SuperJedi224 – 2015-05-27T17:17:18.570

This one works for me: (function(b,c){b/=1;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(" ")) (171 bytes). – Ismael Miguel – 2015-05-27T17:21:47.480

And this one too: (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(" ")) (167 bytes). – Ismael Miguel – 2015-05-27T17:23:48.287

1I just got it down to 162 anyway. – SuperJedi224 – 2015-05-27T17:23:57.733

You can chop it down to 159 if you remove the spaces after the units. – Ismael Miguel – 2015-05-27T17:27:22.510

1You're right, I missed some of the spaces. Thank you for pointing that out. – SuperJedi224 – 2015-05-27T17:28:07.913

1154 bytes: e=273.15,a=prompt(f=1.8).split(" "),b=+a[0],X=b-32/f,c=a[1];alert(c=="F"&&(X+"C\n"+(X+e+"K"))||(c=="C"?b*f+32+"F\n"+(b+e+"K"):b*f-459.67+"F\n"+(b-e+"C"))) – Ismael Miguel – 2015-05-27T17:32:38.373

Sorry, edited my comment on the wrong time. But I've reduced it a little bit – Ismael Miguel – 2015-05-27T17:37:15.660

Your last edit doesn't work right. – SuperJedi224 – 2015-05-27T17:39:55.487

You are right. But Now I can't edit it. – Ismael Miguel – 2015-05-27T17:43:33.317

2

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

Mr.Wizard

Posted 2015-05-25T13:27:14.010

Reputation: 2 481

The OP said in a comment that "You have to only output the other two formats." – lirtosiast – 2015-05-26T22:43:53.873

@Thomas That and other problems (hopefully) fixed. Not very good but I am losing interest. – Mr.Wizard – 2015-05-26T23:00:12.650

1

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?

Wernisch

Posted 2015-05-25T13:27:14.010

Reputation: 2 534