# Create a solar system

Intro

This is based on an actual problem I recently faced while making a computer game and I thought it would make for a nice round of .

There are seven main spectral classes of star which put out varying amounts of heat. The geology of planets around a star are greatly influenced by the amount of heat received from the star, which is a factor of spectral class and distance from the star. Hence Mercury is practically molten, Neptune frozen.

The galaxy in my game is procedurally generated and randomly selecting planet types for given stars turned out to be a real 'if statement hell'!

The challenge

Your method should select one planet from a list of planet types appropriate for the class of star, based on a minimum heat threshold, a maximum heat threshold and a random number. For simplicity this challenge will only use a class G star, just like our sun.

Inputs

An integer heat in the range 4 to 11 representing the amount of heat received by the planet from the star.

Variables

This table shows the possible planets based on heat. Your method should first narrow the available choices based on the heat min and heat max, heat should fall on or between the two. E.g. with a heat of 10 passed in the only choices would be Desert, Iron and Lava.

Planet type    Heat min   Heat max   Random Chance
Gas Giant         4          9            15
Ice               4          6            10
Ice Giant         4          6            10
Gaia class        5          7            10
Dense Atmosphere  7          9            10
Desert            7          10           25
Iron              7          10           14
Lava             10          11           6


Next, the probability of a planet (in the remaining choices) being chosen is its random chances divided by the sum of the random chances of all the choices.

In the above example, the probability of Iron being chosen is 14/(25+14+6).

Output

Return the planet type as a string.

Do the best you can to avoid logic arrowheads. Shortest code wins, points all round for creativity. Happy golfing!

• Should the "class" of "Gaia class" be capitalised like everything else? – Jonathan Allan Feb 24 '18 at 14:43
• @JonathanAllan it's lower case as it's not a proper noun – Absinthe Feb 24 '18 at 15:06
• @Absinthe Then why is Dense Atmosphere uppercase? – Erik the Outgolfer Feb 24 '18 at 15:08
• ... have anyone said that? | Welcome to PPCG, and nice first challenge! – user202729 Feb 24 '18 at 15:24
• @EricDuminil aka an arrowhead anti-pattern, aka nested-if-statement-hell! wiki.c2.com/?ArrowAntiPattern – Absinthe Feb 25 '18 at 13:44

# Jelly, 78 bytes

“'ĖøÆḳƙ’ḃ7ṣ6+\+3r/ċ€×“½½½½©ÐÇı‘
“ŀỊẋ8ƒ³ẈRɼƈñqẋẏȧɱḌ<ṄỴḳ⁾ÆʋeẒĊ'@ƬØƓƝ}ḟ¬»ỴW€ẋ"ÇẎX


A monadic link accepting an integer (in [4,11]) which returns a list of characters.

Try it online!

### How?

Creates the heat ranges of the planets as a list of lists and counts the occurrences of the input heat in those lists to get a list of zeros and ones representing which planet types are possible, then multiplies by the likelihood numbers of the eight planet types to get the distribution. The distribution is used to repeat the planet type names, and finally a uniform random choice is made.

“'ĖøÆḳƙ’ḃ7ṣ6+\+3r/ċ€×“½½½½©ÐÇı‘ - Link 1, getDistribution: integer
“'ĖøÆḳƙ’                        - base 250 integer = 39824688429662
ḃ7                      - to bijective-base 7 = [1,1,2,4,7,1,4,4,6,2,2,2,2,1,5,3,3]
ṣ6                    - split at sixes = [[1,1,2,4,7,1,4,4][2,2,2,2,1,5,3,3]]
\                  - cumulative reduce with:
+3                - add three = [[4,4,5,7,10,4,7,7],[6,6,7,9,11,9,10,10]]
/              - reduce with:
r               -   inclusive range = [[4,5,6],[4,5,6],[5,6,7],[7,8,9],[10,11],[4,5,6,7,8,9],[7,8,9,10],[7,8,9,10]]
ċ€            - count (input) in €ach e.g. for 5: [1, 1, 1, 0,0, 1, 0, 0]
“½½½½©ÐÇı‘ - list of code-page indices        [10,10,10,10,6,15,14,25]
×           - multiply                         [10,10,10, 0,0,15, 0, 0]

“ ... »ỴW€ẋ"ÇẎX - Main link: integer
“ ... »         - compressed string = "Ice\nIce Giant\nGaia class\nDense Atmosphere\nLava\nGas Giant\nIron\nDesert"
Ỵ        - split at new lines = ["Ice","Ice Giant","Gaia class","Dense Atmosphere","Lava","Gas Giant","Iron","Desert"]
W€      - wrap €ach in a list
Ç   - call last link (1) as a monad e.g. for 5: [10,10,10,0,0,15,0,0]
"    - zip with:
ẋ     -   repeat e.g. for 5:  [["Ice","Ice","Ice","Ice","Ice","Ice","Ice","Ice","Ice","Ice"],["Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant"],["Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class"],["Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant"]]
Ẏ  - tighten               ["Ice","Ice","Ice","Ice","Ice","Ice","Ice","Ice","Ice","Ice","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Ice Giant","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gaia class","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant","Gas Giant"]
X - a random choice from that list

• Crazy! Well done. – Absinthe Feb 24 '18 at 15:11
• @Absinthe You can simply upvote. Side note: On Code Golf we typically don't accept answers. – user202729 Feb 24 '18 at 15:12
• @user202729 I'll add votes in a day or two. I was looking over the GitHub page for Jelly trying to unravel this code. I believe Crazy! is most appropriate :) – Absinthe Feb 24 '18 at 15:18
• @Absinthe yes, I believe a descriptive section is often a good thing to have even for non-esoteric language submissions :) – Jonathan Allan Feb 24 '18 at 17:29
• You people are truly insane. – Selvek Feb 25 '18 at 5:20

# R, 225223 183 bytes

Thanks to Giuseppe for clever refactoring to take it down to 188 bytes; the remaining five were shaved off by using less redundant number representations.

i=scan()-4
sample(c("Gas Giant","Ice","Ice Giant","Gaia class","Dense Atmosphere","Desert","Iron","Lava")[l<-c(0,0,0,1,3,3,3,6)<=i&c(5,2,2,3,5,6,6,7)>=i],1,,c(3,2,2,2,2,5,2.8,1.2)[l])


Try it online!

• That's a nice approach, I may have to think about removing my if statement maze if favour of this in C# :) – Absinthe Feb 24 '18 at 18:23
• I suspect saving the logical index rather than using with,data.frame, and subset will be shorter. – Giuseppe Feb 26 '18 at 13:51
• 188 bytes – Giuseppe Feb 26 '18 at 15:13
• @Giuseppe, you can probably gain a few more bytes by using some of my tricks with planet data, but I think I'll also improve mine using your idea of separating the probabilities vector from the rest of the data. – Kirill L. Feb 26 '18 at 15:38

# JavaScript 212

Edit 6 bytes save thx Jonathan Allan

h=>[963,640,640,649,667,1628,924,437].map((z,i)=>(z/8&7)+4>h|z%8+6<h?0:t=r.push(...Array(z>>6).fill(i)),r=[])&&"Gas Giant,Ice,Ice Giant,Gaia class,Dense Atmosphere,Desert,Iron,Lava".split,[r[t*Math.random()|0]]


less golfed

h=>(
r = [],
// heat min,max and chance encoded in base 8 with offsets
// min range 4 to 10, with offset 4, 0 to 6
// max range 6 to 11, with offset 6, 0 to 5
[(4-4)*8 + 9-6 + 15*64,
(4-4)*8 + 6-6 + 10*64,
(4-4)*8 + 6-6 + 10*64,
(5-4)*8 + 7-6 + 10*64,
(7-4)*8 + 9-6 + 10*64,
(7-4)*8 + 10-6+ 25*64,
(7-4)*8 + 10-6+ 14*64,
(10-4)*8+ 11-6+  6*64]
.forEach( (z,i) => (
min = (z / 8 & 7) + 4,
max = z % 8 + 6,
chance = z >> 6,
min > h || max < h
? 0 // out of range
// add current position i repeated 'chance' times
// array size in t
: t = r.push(...Array(chance).fill(i))
),
pos = r[t * Math.random() | 0],
["Gas Giant", "Ice", "Ice Giant", "Gaia class", "Dense Atmosphere", "Desert", "Iron", "Lava"][pos]
)


Test

var F=
h=>[963,640,640,649,667,1628,924,437].map((z,i)=>(z/8&7)+4>h|z%8+6<h?0:t=r.push(...Array(z>>6).fill(i)),r=[])&&"Gas Giant,Ice,Ice Giant,Gaia class,Dense Atmosphere,Desert,Iron,Lava".split,[r[t*Math.random()|0]]

function test()
{
var heat=+H.value
var i,result,hashtable={},rep=1e5
for (i=0;i<rep;i++)
result = F(heat),
hashtable[result] = -~hashtable[result]

console.log('Input',heat)
for (i in hashtable)
{
console.log(i,(hashtable[i]/rep*100).toFixed(2),'%')
}
}
<input id=H type=number min=1 max =15 value=10>
<button onclick='test()'>Test</button>

• A couple of your base 16 numbers are 1 off (should be [3913, 2630, 2630, 2647, 2681, 6522, 3706, 1707]) – Jonathan Allan Feb 24 '18 at 18:55
• I think (but am not 100%) you can save 2 by replacing (z/16&15) with z/16&15. Regardless, you can save 6 bytes using a base 8 compression with offsets of three and six... use [971,648,648,657,675,1636,932,445] with z/8&7+3, z%8+6 and z>>6 :) – Jonathan Allan Feb 24 '18 at 19:13
• @JonathanAllan offsets! Great idea, thx – edc65 Feb 24 '18 at 19:51
• @JonathanAllan i need brackets for (z/8&7)+4 because & has lower priority - it would be 7/8&(7+4) – edc65 Feb 24 '18 at 20:09
• @Shaggy did you see the comment right above yours? (long story short: no) – edc65 Feb 26 '18 at 16:15

# Coconut, 214 195 bytes

t->choice..sum([[n]*g(p)*(g(a)<t<g(b))for*n,a,b,p in'Gas Giant3AF_Ice37A_Ice Giant37A_Gaia class48A_Dense Atmosphere6AA_Desert6BP_Iron6BE_Lava9C6'.split('_')],[])
from random import*

# PHP, 1236 bytes

<?php
$heat = (int)fgets(STDIN);$planets =
[
'Gas Giant' =>        ['heat_min' => 4, 'heat_max' => 9, 'selection_chance' => 15],
'Ice' =>              ['heat_min' => 4, 'heat_max' => 6, 'selection_chance' => 10],
'Ice Giant' =>        ['heat_min' => 4, 'heat_max' => 6, 'selection_chance' => 10],
'Gaia class' =>       ['heat_min' => 5, 'heat_max' => 7, 'selection_chance' => 10],
'Dense Atmosphere' => ['heat_min' => 7, 'heat_max' => 9, 'selection_chance' => 10],
'Desert' =>           ['heat_min' => 7, 'heat_max' => 10, 'selection_chance' => 25],
'Iron' =>             ['heat_min' => 7, 'heat_max' => 10, 'selection_chance' => 14],
'Lava' =>             ['heat_min' => 10, 'heat_max' => 11, 'selection_chance' => 6],
];
foreach ($planets as$planet) {
$chance_sum += ($heat >= $planet['heat_min'] &&$heat <= $planet['heat_max']) *$planet['selection_chance'];
}
while (true) {
foreach ($planets as$name => $planet) {$prob = 100 * ($heat >=$planet['heat_min'] && $heat <=$planet['heat_max']) * $planet['selection_chance'] /$chance_sum;
if (rand(0, 100) < $prob) { echo$name."\n";
exit;
}
}
}
?>


Try it online!