The Most Durable Pokemon Types

9

2

Background

This question is similar to this one. I have provided all of the information needed below. If you are familiar with the other challenge then note that we are ranking all defenses instead of seeing the effectiveness of a single attack. This is important because it means that the tables are inverses of each other and the goal of this challenge is to be without user input.

In Pokemon there are 18 types:

Normal    Fighting  Flying  Poison  Ground  Rock
Bug       Ghost     Steel   Fire    Water   Grass
Electric  Psychic   Ice     Dragon  Dark    Fairy

Pokemon have either one or two unique types that define them (a "type combination"). For example, a Bulbasaur has the type combination Grass/Poison (it has two types, Grass and Poison) and a Charmander has the type combination Fire (having just one type). The order of types does not matter (i.e. Grass/Poison is the same as Poison/Grass).

These types all have strengths and weaknesses:

  • A type can be weak to another type. Fire is weak against Water. This results in Fire having a 2× multiplier against Water.
  • A type can be resistant to another type. Water is resistant to Water. This results in Water having a 0.5× multiplier against Water.
  • A type can be immune to another type. Flying is immune to Ground. This results in Flying having a 0× multiplier against Ground.

Anything else receives a standard 1× multiplier. Normal against Normal would result in a 1× multiplier is an example of this. These strengths and weaknesses can be compounded or negated as well. For example, Fire is weak to Water but a Fire/Water dual type would have a 1× multiplier against Water since the weakness from Fire would negate the resistance from Water. For a full table and a further explanation, see below.

Objective

The goal here is to output a list of all types combinations, sorted in the order of their defensive ability, and listing their numbers of (resistances+immunities), weaknesses, and the ratio between those. Specifically, the sort order is as follows: type combinations with the best ratio of (resistances+immunities) to weaknesses are listed first, and if there is a tie, type combinations with the most resistances and immunities will win the tiebreak. You can produce this list via any means (an obvious method is to do a type effectiveness calculation against each type combination, but you are allowed to store precalculated or partially precalculated output in your program if doing so would make it shorter.)

Type effectiveness table

For a human readable table, see the Pokemon database. Note: the columns of this list are what we are considering. But just in case, here is the table I'm thinking of in a compressed computer-friendly matrix of effectiveness. I've multiplied every value by 2 so we don't have to deal with pesky decimals:

           Attacking type
            (same order)
   Nor   222222422222202222
   Fir   214211224221422211 
D  Wat   211441222222222212
e  Ele   222122224122222212
f  Gra   241114241424222222
e  Ice   242221422222422242 
n  Fig   222222222441122124  
d  Poi   222212114241222221
i  Gro   224044212222122222 
n  Fly   222414120221422222  
g  Psy   222222122214242422 
   Bug   242212121422422222 
T  Roc   114242414122222242
y  Gho   022222012221242422
p  Dra   211114222222224224   
e  Dar   222222422204212124
   Ste   142211404111121211  
   Fai   222222142221220142

Example

If this problem had requested only output for single-type type combinations, then a valid output would look like this:

Steel -> 11/3 = 3.66
Electric -> 3/1 = 3
Poison -> 5/2 = 2.5
Fire -> 6/3 = 2
Water -> 4/2 = 2
Ghost -> 4/2 = 2
Fairy -> 4/2 = 2
Fly -> 4/3 = 1.333
Dragon -> 4/3 = 1.333
Fighting -> 3/3 = 1
Normal -> 1/1 = 1
Ground -> 3/3 = 1
Psychic -> 2/2 = 1
Bug -> 3/3 = 1
Dark -> 3/3 = 1
Grass -> 4/5 = 0.8
Rock -> 4/5 = 0.8
Ice -> 1/4 = 0.25

However, your program will also need to list all of the dual-type combinations in the output, so its output will be considerably longer.

Best of luck! Shortest code in bytes wins.

Devin White

Posted 2016-11-20T21:59:37.547

Reputation: 93

2Related. – Martin Ender – 2016-11-20T22:06:12.090

3And welcome to PPCG! :) – Martin Ender – 2016-11-20T22:06:30.207

1I think this has the obvious problem that the answer is smaller than the data needed to solve the question, and thus a winning solution will just hardcode the output. In order to solve the issue, you probably need to change the challenge to take the type effectiveness matrix as input at runtime. – None – 2016-11-20T22:17:23.550

@ais523 I believe compressing the matrix is supposed to be the core of the challenge, and in principle I see nothing wrong with that (although in this case, unfortunately, this exact table has been the subject of a challenge before). – Martin Ender – 2016-11-20T22:21:27.560

@MartinEnder in that case, how do you judge a solution objectively? The question is [tag:kolmogorov-complexity] in that, as written, it always prints the same answer, and that answer is considerably shorter than the data needed to compute it. So a compression technique that "precomputes" more of the type effectivenesses will lead to a shorter solution. I think the question might need to be placed on hold until it's been clarified what's allowed to be hardcoded in the program and what has to be calculated at runtime and how. – None – 2016-11-20T22:27:51.080

Alternatively, given that the answer is only slightly shorter than the question is, we could just run this as a [tag:kolmogorov-complexity]; it'd probably be quite interesting if run like that. In that case, we should probably have the exact intended output in the question somewhere. – None – 2016-11-20T22:29:18.910

I was actually inspired by that related question. I didn't quite understand the solution so I couldn't adapt it for my question. The core difference is that question takes an attack type and a defending type and computes the damage multiplier. Thus, that question can see a type's strengths whereas I wanted to rank each type by its weaknesses and defenses – Devin White – 2016-11-20T23:11:12.083

OK, I think what this question needs is a specification of exactly how much precalculation the program is allowed to do. I can see two possible questions you can ask here, and it isn't clear which you're asking: a) you can ask for a program that outputs the type ranking, with no restrictions on how, but many of the solutions will likely hardcode the output rather than calculating it; b) you can ask for a program that computes the type ranking, in which case you need to take the type effectiveness table as input to prevent people precalculating it. Which would you find more interesting? – None – 2016-11-20T23:30:31.510

I guess I wasn't clear. I want an output that is similar to the example I gave but with all double types included. 18C2 is 153 different combinations and I wanted those all to be ranked. Would it really be more efficient to hardcode a 153x153 matrix than create code that generates it? – Devin White – 2016-11-20T23:45:28.620

Well, you're only outputting the 153 summarized answers, and the original type matrix has 324 entries. On the other hand, the answers contain strings (generated according to a pattern) and rational numbers, and the original type matrix has only 5 possibilities per cell, so there's clearly scope for compression here. I think the challenge is probably most interesting as a "compression challenge" in which actually doing the calculation suggested is an obvious means of compression to try, and you seem to agree with that, so I'll suggest an edit to make the challenge work under those rules. – None – 2016-11-21T00:07:50.043

OK, I've suggested an edit to make the challenge rules mostly clear; I don't know whether you can accept the edit yourself or whether we'll have to wait for a high-reputation user to accept it. The only remaining issue is output format; do you want to allow bare-bones formats like ["Steel", 11, 3, 3.666666667] (which will likely lead to shorter programs), or do you want to require a specific format? In the latter case, you'll need a rule describing how the fractional numbers are rounded.

– None – 2016-11-21T00:19:23.573

Wow thank you so much for all the help. I see what you mean now by the 153 summarized answers being shorter and I didn't think of that. Hope I didn't cause anyone in here too much headache trying to make my answer into a better question. I think I'm fine with the bare-bones format so I'll make sure to include that in the question as well. – Devin White – 2016-11-21T00:51:06.710

2@MartinEnder It's more than related... If you go over the introduction it's 100% copied and then altered to not look like it's copied. It follows the exact same structure, the starting types are in the same order, formatted the same. It's just blatant plagiarizing without mentioning it and trying to hide it. – orlp – 2016-11-21T12:37:51.550

@orlp I honestly didn't try to plagiarize. I thought of the question on my own and made a Google search. When I saw that question and that it was similar, I figured I'd make a post too. I wrote the post on my own and my question differs in that I do not want input and I want the types to be ranked. I'm new to this so I didn't know I should have linked to his question or made it related. I've added that the question was related in the description. If there's more that I need to do, please instruct me and I'd be happy to do so. – Devin White – 2016-11-22T23:22:25.457

Answers

2

Python 2, 784 bytes

i=['Normal','222222422222202222'],['Fire','214211224221422211'],['Water','211441222222222212'],['Electric','222122224122222212'],['Grass','241114241424222222'],['Ice','242221422222422242'],['Fighting','222222222441122124'],['Poison','222212114241222221'],['Ground','224044212222122222'],['Flying','222414120221422222'],['Psychic','222222122214242422'],['Bug','242212121422422222'],['Rock','114242414122222242'],['Ghost','022222012221242422'],['Dragon','211114222222224224'],['Dark','222222422204212124'],['Steel','142211404111121211'],['Fairy','222222142221220142']
L=[]
for x,X in i:
 for y,Y in i[i.index([x,X]):]:
  S=W=0.
  for a,b in zip(X,Y):A=int(a)*int(b);W+=A>4;S+=A<4
  L+=[([x+'/'+y,x][x==y]+' -> %d/%d'%(S,W),S/W)]
for l in sorted(L, key=lambda l:-l[1]):print'%s = %.2f'%l

Outputs:

Bug/Steel -> 9/1 = 9.00
Steel/Fairy -> 11/2 = 5.50
Normal/Ghost -> 5/1 = 5.00
Water/Ground -> 5/1 = 5.00
Grass/Steel -> 10/2 = 5.00
Poison/Dark -> 5/1 = 5.00
Poison/Steel -> 10/2 = 5.00
Flying/Steel -> 10/2 = 5.00
Dragon/Steel -> 10/2 = 5.00
Normal/Steel -> 12/3 = 4.00
Electric/Poison -> 8/2 = 4.00
Electric/Steel -> 12/3 = 4.00
Ghost/Dark -> 4/1 = 4.00
Water/Steel -> 11/3 = 3.67
Dark/Steel -> 11/3 = 3.67
Steel -> 11/3 = 3.67
Fire/Steel -> 10/3 = 3.33
Fire/Ground -> 6/2 = 3.00
Water/Flying -> 6/2 = 3.00
Electric -> 3/1 = 3.00
Electric/Flying -> 6/2 = 3.00
Electric/Fairy -> 6/2 = 3.00
Ice/Steel -> 9/3 = 3.00
Fighting/Steel -> 9/3 = 3.00
Rock/Steel -> 9/3 = 3.00
Ghost/Steel -> 12/4 = 3.00
Fire/Electric -> 8/3 = 2.67
Water/Poison -> 8/3 = 2.67
Normal/Poison -> 5/2 = 2.50
Water/Electric -> 5/2 = 2.50
Poison -> 5/2 = 2.50
Ground/Flying -> 5/2 = 2.50
Ground/Steel -> 10/4 = 2.50
Psychic/Steel -> 10/4 = 2.50
Fire/Flying -> 7/3 = 2.33
Water/Fairy -> 7/3 = 2.33
Electric/Ghost -> 7/3 = 2.33
Normal/Electric -> 4/2 = 2.00
Normal/Fairy -> 4/2 = 2.00
Fire -> 6/3 = 2.00
Fire/Poison -> 8/4 = 2.00
Fire/Bug -> 6/3 = 2.00
Fire/Fairy -> 8/4 = 2.00
Water -> 4/2 = 2.00
Water/Ghost -> 8/4 = 2.00
Electric/Bug -> 4/2 = 2.00
Fighting/Poison -> 6/3 = 2.00
Poison/Fairy -> 6/3 = 2.00
Psychic/Ghost -> 4/2 = 2.00
Ghost -> 4/2 = 2.00
Ghost/Fairy -> 4/2 = 2.00
Dragon/Fairy -> 8/4 = 2.00
Fairy -> 4/2 = 2.00
Fire/Ghost -> 9/5 = 1.80
Normal/Fire -> 7/4 = 1.75
Fire/Rock -> 7/4 = 1.75
Fire/Dark -> 7/4 = 1.75
Poison/Dragon -> 7/4 = 1.75
Normal/Water -> 5/3 = 1.67
Fire/Water -> 5/3 = 1.67
Fire/Dragon -> 5/3 = 1.67
Water/Bug -> 5/3 = 1.67
Electric/Fighting -> 5/3 = 1.67
Ghost/Dragon -> 8/5 = 1.60
Fire/Fighting -> 6/4 = 1.50
Water/Dragon -> 3/2 = 1.50
Electric/Dragon -> 6/4 = 1.50
Electric/Dark -> 6/4 = 1.50
Poison/Ground -> 6/4 = 1.50
Poison/Flying -> 6/4 = 1.50
Poison/Rock -> 6/4 = 1.50
Poison/Ghost -> 6/4 = 1.50
Ground/Fairy -> 6/4 = 1.50
Flying/Dragon -> 6/4 = 1.50
Rock/Fairy -> 6/4 = 1.50
Fire/Psychic -> 7/5 = 1.40
Water/Fighting -> 7/5 = 1.40
Water/Dark -> 7/5 = 1.40
Grass/Fairy -> 7/5 = 1.40
Fighting/Dragon -> 7/5 = 1.40
Dragon/Dark -> 7/5 = 1.40
Normal/Flying -> 4/3 = 1.33
Fire/Grass -> 4/3 = 1.33
Fighting/Dark -> 4/3 = 1.33
Poison/Psychic -> 4/3 = 1.33
Ground/Dragon -> 4/3 = 1.33
Flying -> 4/3 = 1.33
Dragon -> 4/3 = 1.33
Dark/Fairy -> 4/3 = 1.33
Normal/Dragon -> 5/4 = 1.25
Water/Rock -> 5/4 = 1.25
Electric/Ground -> 5/4 = 1.25
Electric/Psychic -> 5/4 = 1.25
Electric/Rock -> 5/4 = 1.25
Grass/Poison -> 5/4 = 1.25
Fighting/Bug -> 5/4 = 1.25
Fighting/Ghost -> 5/4 = 1.25
Poison/Bug -> 5/4 = 1.25
Flying/Dark -> 5/4 = 1.25
Water/Psychic -> 6/5 = 1.20
Grass/Ghost -> 6/5 = 1.20
Ground/Ghost -> 6/5 = 1.20
Flying/Rock -> 6/5 = 1.20
Flying/Ghost -> 6/5 = 1.20
Flying/Fairy -> 6/5 = 1.20
Bug/Ghost -> 6/5 = 1.20
Bug/Fairy -> 6/5 = 1.20
Normal -> 1/1 = 1.00
Normal/Fighting -> 4/4 = 1.00
Normal/Ground -> 4/4 = 1.00
Normal/Psychic -> 2/2 = 1.00
Normal/Bug -> 3/3 = 1.00
Normal/Rock -> 5/5 = 1.00
Normal/Dark -> 3/3 = 1.00
Fire/Ice -> 4/4 = 1.00
Water/Grass -> 3/3 = 1.00
Electric/Grass -> 4/4 = 1.00
Grass/Fighting -> 6/6 = 1.00
Grass/Dark -> 7/7 = 1.00
Ice/Poison -> 5/5 = 1.00
Ice/Ghost -> 5/5 = 1.00
Ice/Fairy -> 4/4 = 1.00
Fighting -> 3/3 = 1.00
Fighting/Flying -> 5/5 = 1.00
Fighting/Fairy -> 5/5 = 1.00
Ground -> 3/3 = 1.00
Ground/Bug -> 4/4 = 1.00
Ground/Rock -> 6/6 = 1.00
Ground/Dark -> 6/6 = 1.00
Psychic/Dragon -> 6/6 = 1.00
Psychic/Fairy -> 3/3 = 1.00
Bug -> 3/3 = 1.00
Bug/Dragon -> 5/5 = 1.00
Bug/Dark -> 5/5 = 1.00
Rock/Ghost -> 6/6 = 1.00
Rock/Dark -> 7/7 = 1.00
Dark -> 3/3 = 1.00
Grass/Psychic -> 6/7 = 0.86
Fighting/Rock -> 6/7 = 0.86
Normal/Grass -> 5/6 = 0.83
Grass/Bug -> 5/6 = 0.83
Fighting/Ground -> 5/6 = 0.83
Ground/Psychic -> 5/6 = 0.83
Rock/Dragon -> 5/6 = 0.83
Grass -> 4/5 = 0.80
Grass/Flying -> 4/5 = 0.80
Flying/Psychic -> 4/5 = 0.80
Flying/Bug -> 4/5 = 0.80
Rock -> 4/5 = 0.80
Electric/Ice -> 3/4 = 0.75
Grass/Ground -> 3/4 = 0.75
Ice/Flying -> 3/4 = 0.75
Ice/Bug -> 3/4 = 0.75
Psychic/Rock -> 5/7 = 0.71
Grass/Dragon -> 4/6 = 0.67
Ice/Rock -> 4/6 = 0.67
Ice/Dark -> 4/6 = 0.67
Fighting/Psychic -> 2/3 = 0.67
Psychic -> 2/3 = 0.67
Psychic/Bug -> 4/6 = 0.67
Bug/Rock -> 2/3 = 0.67
Ice/Dragon -> 3/5 = 0.60
Grass/Ice -> 4/7 = 0.57
Normal/Ice -> 2/4 = 0.50
Water/Ice -> 2/4 = 0.50
Grass/Rock -> 2/4 = 0.50
Ice/Fighting -> 3/6 = 0.50
Psychic/Dark -> 1/2 = 0.50
Ice/Ground -> 2/5 = 0.40
Ice/Psychic -> 2/6 = 0.33
Ice -> 1/4 = 0.25

TFeld

Posted 2016-11-20T21:59:37.547

Reputation: 19 246

Awesome. Exactly what I wanted. Thanks mate! – Devin White – 2016-11-29T13:40:34.377