Bangun Spektrometer Massal!

8

Tantangan

Mengingat massa molekul resolusi tinggi dari molekul organik, mengeluarkan rumus molekul molekul.

Penjelasan

Input akan berupa angka tunggal hingga tiga tempat desimal presisi, massa molekul relatif dari molekul tersebut.

Di sini, massa molekul didefinisikan sebagai jumlah massa atom dalam senyawa. Karena Anda hanya menemukan rumus molekul senyawa organik, massa atom yang perlu Anda ketahui adalah:

  • C , Karbon: 12.011
  • H , Hidrogen: 1,008
  • O , Oksigen: 15,999
  • N , Nitrogen: 14.007

Formula Anda seharusnya hanya mengandung karbon, hidrogen, oksigen atau nitrogen.

Saat menulis rumus, itu harus berbentuk:

CaHbOcNd

Di mana unsur-unsur harus dalam agar ( C -> H -> O -> N, jadi C2O8N4H6harus C2H6O8N4) dan a, b, cdan dadalah angka dari elemen sebelumnya dalam molekul (yaitu C2berarti bahwa ada dua atom karbon dalam molekul).

Jika a, b, catau dyang nol, elemen yang tidak boleh dimasukkan dalam rumus (misalnya C2H6O2N0harus C2H6O2). Akhirnya, jika a, b, catau dyang satu, Anda tidak harus menyertakan nomor dalam formula (misalnya C1H4harus CH4).

Input akan selalu valid (yaitu akan ada molekul dengan massa itu). Jika inputnya ambigu (beberapa molekul memiliki massa yang sama), Anda hanya harus mengeluarkan satu dari molekul tersebut. Bagaimana Anda memilih molekul ini, itu terserah Anda.

Contoh yang berhasil

Misalkan inputnya 180.156, hanya ada satu kombinasi elemen yang dapat memiliki massa molekul ini:

12.011*6 + 1.008*12 + 15.999*6 + 14.007*0 = 180.156

Jadi ada:

  • 6 Karbon
  • 12 Hidrogen
  • 6 Oksigen
  • 0 Nitrogen

Karena itu, output Anda harus:

C6H12O6

Lebih banyak contoh

Input -> Output

28.054 -> C2H4
74.079 -> C3H6O2
75.067 -> C2H5O2N
18.015 -> H2O

Kemenangan

Kode terpendek dalam byte menang.

Peluruhan Beta
sumber
2
Bagaimana jika inputnya ambigu?
NoOneIsHere
@NoOneIsHere AFAIK input tidak boleh ambigu, tapi saya akan menambahkannya ke dalam aturan.
Beta Decay
Masukan dapat diambil sebagai int (yaitu, tidak ada periode - etena akan 28054)
Stephen
4
12.011adalah massa atom relatif dari karbon, yang merupakan rata-rata tertimbang dari massa isotop relatif dari isotop. Dalam spektrometer massa, di mana isotop yang berbeda dibedakan, Anda harus melihat dengan tepat 12. Mirip dengan atom lainnya.
Leaky Nun
2
Untuk pengujian yang menyenangkan, perhatikan bahwa input 672.336memiliki 24 solusi yang memungkinkan, termasuk nitrogen murni dan larutan hidrogen murni.
Greg Martin

Jawaban:

2

Mathematica, 108 byte

Print@@Join@@({Characters@"CHON",#}ᵀ/.a_/;Last@a<2:>Table@@a)&/@{12011,1008,15999,14007}~FrobeniusSolve~#&

Fungsi murni mengharapkan input sebagai bilangan bulat (1000 kali massa molekul relatif); itu mencetak semua jawaban yang mungkin untuk STOUD (dan mengembalikan array Nulls).

Pengangkatan berat dilakukan oleh builtin {12011,1008,15999,14007}~FrobeniusSolve~#, yang menemukan semua kombinasi bilangan bulat tidak negatif dari bobot hardcoded yang sama dengan input. {Characters@"CHON",#}ᵀmenempatkan setiap kombinasi tersebut dalam bentuk seperti {{"C", 0}, {"H", 1}, {"O", 2}, {"N", 3}}. ( sebenarnya adalah karakter matematika 3 byte U + F3C7.)

Aturan transformasi /.a_/;Last@a<2:>Table@@amengubah pasangan formulir {x, 0}ke {}dan pasangan formulir {x, 1}ke {x}(dan meludahkan kesalahan saat mencoba menerapkan ke seluruh ekspresi juga). Kemudian Print@@Join@@cetak hasilnya dalam bentuk yang benar, hindari kebutuhan untuk melemparkan bilangan bulat sebagai string dan menyatu.

Greg Martin
sumber
Apa hasil dari 672336? :)
Beta Decay
The tampaknya menjadi karakter yang salah. Seharusnya .
Martin Ender
Ya, harus membuat pilihan antara mudah dibaca dan mudah dipotong / ditempelkan.
Greg Martin
2

Python 2 , 242 byte

b=[12011,1008,15999,14007]
def p(m):
 if m in b:x=[0,]*4;x[b.index(m)]=1;return x
 elif m<1:return 0
 else:
  for i in range(4):
   x=p(m-b[i])
   if x:x[i]+=1;return x
  return 0
print''.join(a+`n`*(n>1)for n,a in zip(p(input()),'CHON')if n)

Cobalah online!
Fungsi rekursif, inputnya adalah bilangan bulat (1000 kali massa molekul relatif) terima kasih Stephen S untuk idenya


Mesin saya mengambil 40 Segs untuk gilirannya 672336menjadi C33H115O3N8dengan kode dimodifikasi ini . Ini berisi tabel pencarian untuk hit / gagal untuk mengurangi jumlah panggilan rekursif dan optimasi untuk menghitung elemen beberapa kali (jika massanya cukup tinggi)

tongkat
sumber
Mengapa 180156batas waktu ketika semua kasus uji sangat cepat? (tanpa hit cache)
Beta Decay
@ BetaDecay hmm, bisa jadi 18015sebaliknya?
Rod
Tidak, 18015ini H2O, tidakC6H12O6
Beta Decay
1

JavaScript (ES6), 159 158 byte

Tidak terlalu cepat ...

w=>[...Array(w**4|0)].some((_,n)=>![12011,1008,15999,14007].reduce((p,c,i)=>p-c*(x[i]=n%w|!(n/=w)),w*1e3,x=[]))&&x.map((v,i)=>('CHON'[i]+v).slice(0,v)).join``

Demo


Versi lebih cepat, 174 173 byte

w=>[...Array(w**3|0)].some((_,n)=>r=(d=w*1e3-14007*(a=n/w/w%w|0)-15999*(b=n/w%w|0)-12011*(c=n%w|0))%1008|d<0?0:[c,d/1008,b,a])&&r.map((v,i)=>('CHON'[i]+v).slice(0,v)).join``

Semua uji kasus

Arnauld
sumber