15
\$\begingroup\$

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!
\$\endgroup\$
  • \$\begingroup\$ totally different but related: Drawing Lewis Structures of Alkanes \$\endgroup\$ – Not that Charles Nov 20 '15 at 20:18
  • \$\begingroup\$ So we can assume that the input will be correct formulas? \$\endgroup\$ – TanMath Nov 20 '15 at 20:26
  • \$\begingroup\$ @TanMath, yes, you don't have to worry about invalid formulas \$\endgroup\$ – Adnan Nov 20 '15 at 20:28
  • \$\begingroup\$ "consistently use spaces" - would consistently using 0 spaces count? \$\endgroup\$ – Mego Nov 20 '15 at 22:59
  • 1
    \$\begingroup\$ @Mego, no. Using 0 spaces is not using spaces at all, so the rule doesn't apply \$\endgroup\$ – Adnan Nov 20 '15 at 23:07

18 Answers 18

1
\$\begingroup\$

Pyth, 40 bytes

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

Try it online. Test suite.

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

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.

\$\endgroup\$
4
\$\begingroup\$

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);
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Good 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). \$\endgroup\$ – TNT Nov 20 '15 at 21:38
  • \$\begingroup\$ 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) \$\endgroup\$ – Addison Crump Nov 20 '15 at 21:43
  • \$\begingroup\$ 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. \$\endgroup\$ – TNT Nov 20 '15 at 21:53
  • \$\begingroup\$ And the fact that command line arguments is acceptable in place of STDIN is new (and rather helpful) news to me. :) \$\endgroup\$ – TNT Nov 20 '15 at 21:55
  • 1
    \$\begingroup\$ @VoteToClose Yes, you are hurting yourself with Java. \$\endgroup\$ – Cows quack Nov 21 '15 at 6:07
4
\$\begingroup\$

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)
\$\endgroup\$
3
\$\begingroup\$

Javascript ES6, 63 * .9 = 56.7 bytes

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

Similar to my ESMin answer.

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

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

\$\endgroup\$
  • \$\begingroup\$ You spend six bytes on spacing, but gain only five bytes from the bonus, so it's not worth it. \$\endgroup\$ – lirtosiast Nov 26 '15 at 2:58
2
\$\begingroup\$

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`
\$\endgroup\$
2
\$\begingroup\$

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.
\$\endgroup\$
  • \$\begingroup\$ 2r_[[~]W=_2/(3*)\_2-]"+%dO2>%dH2O+%dCO2"e% saves a byte. \$\endgroup\$ – Dennis Nov 21 '15 at 5:10
2
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

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");
\$\endgroup\$
1
\$\begingroup\$

𝔼𝕊𝕄𝕚𝕟, 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
\$\endgroup\$
  • \$\begingroup\$ Whoever downvoted my answer, could I please get an explanation? \$\endgroup\$ – Mama Fun Roll Nov 22 '15 at 3:42
1
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ You don't need a space between print and a " character, and the CO2 variable could be named something shorter :) \$\endgroup\$ – undergroundmonorail Nov 20 '15 at 20:54
  • \$\begingroup\$ @undergroundmonorail thanks \$\endgroup\$ – TanMath Nov 20 '15 at 20:56
  • \$\begingroup\$ 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) \$\endgroup\$ – undergroundmonorail Nov 20 '15 at 21:14
1
\$\begingroup\$

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.
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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);
}
\$\endgroup\$
1
\$\begingroup\$

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

\$\endgroup\$
1
\$\begingroup\$

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"
\$\endgroup\$
0
\$\begingroup\$

Jelly, 33 bytes

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

Try it online!

The bonus doesn't help here.

\$\endgroup\$

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.