Back to the chemistry class

15

3

Introduction

One of the first things I learned in chemistry, was giving the formula for the combustion of alkanes. The most basic example was: 2CH4 + 4O2 > 4H2O + 2CO2. Note that the equation could have been simplified by dividing every coefficient by 2, we would get CH4 + 2O2 > 2H2O + CO2. To make things easier, we are going to ignore this step.

You can see that with the combustion of any alkane, oxygen is used. After the reaction, only CO2 and H2O are made.

The task:

Give a complete program that takes input from STDIN or the nearest possible equivalent, and outputs the total reaction using STDOUT or the nearest possible equivalent.

The input will always be in the form C(n)H(2n+2), with n > 0. These are some example inputs:

CH4
C2H6
C3H8
C4H10
C5H12
C6H14

etc.

A useful tip:

Every alkane has a standard pattern in the combustion reaction:

2C(n)H(2n+2) + (3n+1)O2 > (2n+2)H2O + (2n)CO2

e.g.

C4H10 gives the following equation: 2C(4)H(2*4+2) + (3*4+1)O2 > (2*4+2)H2O + (2*4)CO2. After calculating everything, we get this final equation: 2C4H10 + 13O2 > 10H2O + 8CO2

Examples:

input:  CH4
output: 2CH4 + 4O2 > 4H2O + 2CO2

input:  C3H8
output: 2C3H8 + 10O2 > 8H2O + 6CO2

input:  C4H10
output: 2C4H10 + 13O2 > 10H2O + 8CO2

input:  C12H26
output: 2C12H26 + 37O2 > 26H2O + 24CO2

Rules:

  • You need to provide a full program.
  • Your program needs to take input from STDIN, or the nearest equivalent if not possible.
  • Your program needs to output using STDOUT, or the nearest equivalent if not possible.
  • Note that I used spaces for the examples to increase readability, these are not necessary. 2CH4 + 4O2 > 4H2O + 2CO2 and 2CH4+4O2>4H2O+2CO2 are both valid outputs. However, if you consistently use spaces for the output, you get a -10% bonus
  • This is , so the program with the least amount of bytes wins!

Adnan

Posted 2015-11-20T19:59:51.837

Reputation: 41 965

totally different but related: Drawing Lewis Structures of Alkanes

– Not that Charles – 2015-11-20T20:18:02.320

So we can assume that the input will be correct formulas? – TanMath – 2015-11-20T20:26:23.007

@TanMath, yes, you don't have to worry about invalid formulas – Adnan – 2015-11-20T20:28:47.093

"consistently use spaces" - would consistently using 0 spaces count? – Mego – 2015-11-20T22:59:34.757

1@Mego, no. Using 0 spaces is not using spaces at all, so the rule doesn't apply – Adnan – 2015-11-20T23:07:01.043

Is C1H4 valid? Or it has to be CH4? – Zereges – 2015-11-20T23:23:31.640

@Zereges, it has to be CH4 – Adnan – 2015-11-20T23:25:22.860

I'm disappointed at the lack of Unicode subscripts. – Neil – 2015-11-21T17:27:40.320

Is a newline character required at the end of the output? – Tom Carpenter – 2015-11-22T04:18:07.293

@TomCarpenter no, that is not required – Adnan – 2015-11-22T06:38:52.327

Answers

1

Pyth, 40 bytes

s[2z\+h*3Jv|hctz\H\1"O2>"yhJ"H2O+"yJ"CO2

Try it online. Test suite.

PurkkaKoodari

Posted 2015-11-20T19:59:51.837

Reputation: 16 699

7

Python 3, 86 * 0.9 = 77.4 bytes

s=input()
N=int(s.split('H')[1])
print("2%s + %dO2 > %dH20 + %dCO2"%(s,N*1.5-2,N,N-2))

Extracts the number of H's rather than the number of C's from the input. This avoid special-casing CH4 and simplifies the output expressions in terms of N=2n+2.

The output has parameters plugged in via string formatting. The first summand is just the input string, and the rest have calculated numbers plugged in. Note that N*1.5-2 (same as N*3/2-2) gives a float, but the string formatting converts it to an int.

xnor

Posted 2015-11-20T19:59:51.837

Reputation: 115 687

4

Java, 0.9*202 = 181.8 bytes

Sometimes, I wonder if I'm just hurting myself with Java.

Thanks to @TNT and @TFeld for shaving off a good 20 bytes!

class A{public static void main(String[]a){String s=a[0].substring(1,a[0].indexOf("H"));long n=Long.parseLong((s.length()>0)?s:"1");System.out.printf("2%s + %dO2 > %dH2O + %dCO2",a[0],3*n+1,2*n+2,2*n);}}

Pretty simple. Basically, I cut the input from C to H, and get that substring. If it's nothing, I set n to one. Otherwise, I set it to the number between C and H. The code following just prints it out and puts it into proper notation.

Ungolfed:

class A{
    public static void main(String[]a) {
         String s=a[0].substring(1,a[0].indexOf("H"));
         long n=Long.parseLong((s.length()>0)?s:"1");
         System.out.printf("2%s + %dO2 > %dH2O + %dCO2",a[0],3*n+1,2*n+2,2*n);
    }
}

Addison Crump

Posted 2015-11-20T19:59:51.837

Reputation: 10 763

2Good answer, but you must use STDIN and not command line args. Though you could shorten it by using printf instead of + (-11 from your raw score if I counted correctly). – TNT – 2015-11-20T21:38:44.083

I've been told that using command line arguments is an acceptable alternative to STDIN. Also, could you clarify how you mean for me to use printf? (A little finicky on that, haven't used it before. :D) – Addison Crump – 2015-11-20T21:43:47.507

printf uses mechanics from java.util.Formatter. You can have a string to print such as "%d" in your print statement and after it some value or variable that will be printed instead. It can be useful in situations where you have a lot of variables to print, for example. – TNT – 2015-11-20T21:53:03.577

And the fact that command line arguments is acceptable in place of STDIN is new (and rather helpful) news to me. :) – TNT – 2015-11-20T21:55:10.787

@TNT I've also been told that it depends on the situation as well. But, yes, it is defaultly permitted. I'm in the midst of a debate currently on whether or not it is accepted for this question specifically. – Addison Crump – 2015-11-20T21:57:21.910

@TNT I honestly still have no idea how to use printf. Can you help me with it, please?

– Addison Crump – 2015-11-20T22:01:58.290

Using printf:

System.out.printf("2%s + %d2 > %d2O + %dO2",a[0],3*n+1,2*n+2,2*n); – TFeld – 2015-11-20T22:15:41.557

@TFeld Doesn't quite work - I'll use something similar, thanks. I get it now. :D – Addison Crump – 2015-11-20T22:18:14.527

Yeah, I'm not sure what happened when i copied it... It seems the first letter is missing from each 'group'

Correctly should be: System.out.printf("2%s + %dO2 > %dH2O + %dCO2",a[0],3*n+1,2*n+2,2*n); – TFeld – 2015-11-20T22:21:01.583

@TFeld Yup, that's what I derived from it - thank you so much! – Addison Crump – 2015-11-20T22:21:36.660

Glad you got it to work! By the way, I posted the wrong example link; I meant to post this one. :P

– TNT – 2015-11-21T00:10:17.393

1@VoteToClose Yes, you are hurting yourself with Java. – user41805 – 2015-11-21T06:07:09.790

4

Python 2, 122 91*0.9 = 81.9 bytes

i=input()
n=2*int(i[1:i.find('H')]or 1)
print'2%s + %dO2 > %dH2O + %dCO2'%(i,n*3/2+1,n+2,n)

TFeld

Posted 2015-11-20T19:59:51.837

Reputation: 19 246

3

Javascript ES6, 63 * .9 = 56.7 bytes

_=>`2${_} + ${$=_.split`H`[1],$*1.5-2}O2 > ${$}H2O + ${$-2}CO2`

Similar to my ESMin answer.

Mama Fun Roll

Posted 2015-11-20T19:59:51.837

Reputation: 7 234

3

Pyth, 69 bytes*0.9 = 62 63*0.9 = 57 56*0.9 = 50 53*0.9 = 48 bytes

Js>z+xz\H1s[\2z%" + %dO2 > %dH2O + %dCO2"[-*1.5J2J-J2

It is just like xnor's answer, where I use the H values. A variable J is used to store the amount of H's in the molecular formula of the molecule.

Try it here

TanMath

Posted 2015-11-20T19:59:51.837

Reputation: 1 431

You spend six bytes on spacing, but gain only five bytes from the bonus, so it's not worth it. – lirtosiast – 2015-11-26T02:58:55.880

2

Javascript ES6, 96*0.9 = 86.4

f=s=>`2C${(n=(s.match(/\d+(?!.*\d)/)[0]-2))>2?n/2:''}H${n+2} + ${1.5*n+1}O2 > ${n+2}H2O + ${n}CO2`

Dendrobium

Posted 2015-11-20T19:59:51.837

Reputation: 2 412

2

CJam, 45 44 bytes

2r_'H/1=[i_((_2/1$+)@@]"+%dO2>%dH2O+%dCO2"e%

Try it online

To avoid special casing CH4, I don't use the first number at all, and only extract the number after the H. This gives the value of 2n+2. The remaining values are then calculated based on that, and formatted.

Explanation:

2       Push leading 2 for output.
r       Get input.
_'H/    Copy and split at 'H.
1=      Take second part after split, this is 2n+2.
[       Start list.
  i       Convert string value to integer.
  _((     Copy and decrement twice, giving 2n.
  _2/     Copy and divide by 2, giving n.
  1$      Copy the 2n to the top.
  +       Add, to get 3n.
  )       Increment, giving 3n+1. We now have 2n+2, 2n, 3n+1 on stack.
  @@      Rotate top 3 entries twice, to get 3n+1, 2n+2, 2n.
]       Close list.
"+%dO2>%dH2O+%dCO2"
        Format string for output.
e%      "printf" operator.

Reto Koradi

Posted 2015-11-20T19:59:51.837

Reputation: 4 870

2r_[[~]W=_2/(3*)\_2-]"+%dO2>%dH2O+%dCO2"e% saves a byte. – Dennis – 2015-11-21T05:10:52.403

2

Perl, (84 + 1) * 0.9 = 76.5

(+1 char for running with the -n flag)

My first Perl golf!

@x=(1,m/C(\d)/g);$n=$x[$#x];say"2$_ + ".(3*$n+1)."O2 > ".(($n*=2)+2)."H20 + ${n}CO2"

It's important that STDIN not contain a trailing newline. Example usage:

llama@llama:...code/perl/ppcg64412chemistry$ printf CH4 | perl -n chemistry.pl
2CH4 + 4O2 > 4H20 + 2CO2

Ungolfed-ish:

#!/usr/bin/perl
use 5.10.0;

$_ = 'C3H8';
my @x = (1, m/C(\d)/g);
my $n = $x[$#x];
say "2$_ + ".(3*$n+1)."O2 > ".(($n*=2)+2)."H20 + ${n}CO2";

The lines

my @x = (1, m/C(\d)/g);
my $n = $x[$#x];

are fairly interesting here. $#x represents the "last populated index" of @x (and SE's syntax highlighting thinks it's a comment because it's dumb), so $x[$#x] will select the captured part of the C(\d) regex if it exists, or 1 otherwise. (Perl doesn't care that it'll be a string in all other cases except 1; you can use numerical operators on strings just fine in Perl.)

Doorknob

Posted 2015-11-20T19:59:51.837

Reputation: 68 138

1

Excel, 123 * 0.9 = 110.7 bytes

=="2"&A1&" + "&(3*MID(A1,FIND("H",A1)+1,9)/2-2)&"O2 > "&MID(A1,FIND("H",A1)+1,9)&"H2O + "&(MID(A1,FIND("H",A1)+1,9)-2)&"CO2"

If we could take CH4 input as C1H4, can be reduced to 122 * 0.9 = 109.8 bytes

="2"&A1&" + "&3*MID(A1,2,FIND("H",A1)-2)+1&"O2"&" > "&MID(A1,FIND("H",A1)+1,9)&"H2O + "&(MID(A1,FIND("H",A1)+1,9)-2)&"CO2"

Wernisch

Posted 2015-11-20T19:59:51.837

Reputation: 2 534

1

Python, 0.9*195 = 175 0.9*190=171 0.9*148 = 133 bytes

i=raw_input()
O=3*int(i[1:i.find('H')]or 1)+1;C=2*int(i[1:i.find('H')]or 1);print"2"+i+" + "+`O`+"O2"+" > "+i[i.find('H')+1:]+"H2O"+ " + "+`C`+"CO2"

Try it here

TanMath

Posted 2015-11-20T19:59:51.837

Reputation: 1 431

You don't need a space between print and a " character, and the CO2 variable could be named something shorter :) – undergroundmonorail – 2015-11-20T20:54:15.550

@undergroundmonorail thanks – TanMath – 2015-11-20T20:56:53.707

Since i[1] is guaranteed to be either "H" or a digit, you can save another byte with if i[1]>"9" (or replace "9" with any other character with an ascii value from 58 to 71) – undergroundmonorail – 2015-11-20T21:14:39.103

1

JS, 118 (106) bytes

x=prompt();y=x.replace("CH","C1H").match(/\d{1,}/g)[0];alert(2+x+" + "+(3*y+1)+"O2 > "+(2*y+2)+"H2O + "+(2*y)+"CO2");

Nautilus

Posted 2015-11-20T19:59:51.837

Reputation: 221

1

C++, 160 * 0.9 = 144 bytes

#include<iostream>
int main(){int n=1,t;std::cin.get();std::cin>>n;t=2*n;printf("2C");n-1&&printf("%i",n);printf("H%i + %iO2 > %iH2O + %iCO2",t+2,t+n+1,t+2,t);}

A bit more that I expected. Reads first char and discards it, then reads int and outputs the result. Problem is with n being 1. I can't think of shorter way to output it.

Ungolfed

#include <iostream>
int main()
{
    int n = 1, t;
    std::cin.get();
    std::cin >> n;
    t = 2 * n;
    printf("2C");
    n - 1 && printf("%i", n);
    printf("H%i + %iO2 > %iH2O + %iCO2", t + 2, t + n + 1, t + 2, t);
}

Zereges

Posted 2015-11-20T19:59:51.837

Reputation: 1 165

1

, 51 * .9 = 45.9 chars / 64 * .9 = 57.6 bytes

a=ïČ`H”[1],`2⦃ï} + ⦃a*1.5-2}O2 > ⦃a}H2O + ⦃a-2}CO2`

Try it here (Firefox only).

Explanation

a=ïČ`H”[1],      // split input along H to get 2n+2
`  2⦃ï}          // 2C(n)H(2n+2) – this is the same as 2[input alkane's formula]
   + ⦃a*1.5-2}O2 // + 2(3n+1)O2
   > ⦃a}H2O      // > (2n+2)H2O
   + ⦃a-2}CO2    // + (2n)O2
`                // implicitly output the template string above

Mama Fun Roll

Posted 2015-11-20T19:59:51.837

Reputation: 7 234

Whoever downvoted my answer, could I please get an explanation? – Mama Fun Roll – 2015-11-22T03:42:08.873

1

F#, 113

let s=stdin.ReadLine()
float s.[1+s.IndexOf 'H'..]|>fun f->printf"2%s + %gO2 > %gH2O + %gCO2"s<|f*1.5-2.<|f<|f-2.

Sehnsucht

Posted 2015-11-20T19:59:51.837

Reputation: 151

1

MATLAB, 96 * 0.9 = 86.4 bytes

s=input('');i=[sscanf(s,'C%dH'),1];n=i(1);fprintf('%s + %dO2 > %dH2O + %dCO2',s,3*n+1,2*n+2,2*n)

Fairly self explanatory. Takes an input string (need to wrap it in quote marks so MATLAB doesn't try to execute it!). Then converts the number between the C and the H in the input to decimal. The value 1 is appended as an array to the output of sscanf so that in the case CH4 when we extract the first index in the array into n we get a 1 if there was no number between the C and H. Then just prints out with the spaces following the formula in the question.

This should also work with Octave using the online interpreter here.

Tom Carpenter

Posted 2015-11-20T19:59:51.837

Reputation: 3 990

1

Clojure/ClojureScript, 98*0.9 = 88.2 bytes

#(let[n(max 1(int((re-find #"C(.*)H"%)1)))m(* 2 n)](str "2"%" + "(inc(* 3 n))"O2 > "(+ 2 m)"H2O + "m"CO2"))

Creates an anonymous function. Try it by going here and entering (def f #(let...)), then (f "C3H8").

MattPutnam

Posted 2015-11-20T19:59:51.837

Reputation: 521

0

Jelly, 33 bytes

ṣ”HṪVµ2³”+2⁸_©+H“O2>”⁸“H2O+”®“CO2

Try it online!

The bonus doesn't help here.

Erik the Outgolfer

Posted 2015-11-20T19:59:51.837

Reputation: 38 134