# Path of exile map combinations

This question will feature a mechanic from the game "Path Of Exile" in this game there are things called MAPS they are items that you can use to open high level areas, you can also combine 3 of them to get a upgraded one which will be the task of this challenge. The upgrade combinations are as follow:

A Crypt Map 68 -> Sewer Map
E Dungeon Map 68 -> Channel Map
I Grotto Map 68 -> Thicket Map
O Dunes Map 68 -> Mountain Ledge Map
U Pit Map 68 -> Cemetery Map
T Tropical Island Map 68 -> Arcade Map
N Desert Map 68 -> Wharf Map
S Sewer Map 69 -> Ghetto Map
H Channel Map 69 -> Spider Lair Map
R Thicket Map 69 -> Vaal Pyramid Map
D Mountain Ledge Map 69 -> Reef Map
L Cemetery Map 69 -> Quarry Map
C Arcade Map 69 -> Mud Geyser Map
M Wharf Map 69 -> Museum Map
W Ghetto Map 70 -> Arena Map
F Spider Lair Map 70 -> Overgrown Shrine Map
G Vaal Pyramid Map 70 -> Tunnel Map
Y Reef Map 70 -> Shore Map
P Quarry Map 70 -> Spider Forest Map
B Mud Geyser Map 70 -> Promenade Map
V Museum Map 70 -> Arena Map
K Arena Map 71 -> Underground Sea Map
J Overgrown Shrine Map 71 -> Pier Map
X Tunnel Map 71 -> Bog Map
Q Shore Map 71 -> Graveyard Map
Z Spider Forest Map 71 -> Coves Map
Ó Promenade Map 71 -> Villa Map
É Underground Sea Map 72 -> Temple Map
Á Pier Map 72 -> Arachnid Nest Map
Í Bog Map 72 -> Strand Map
Ú Graveyard Map 72 -> Dry Woods Map
Ü Coves Map 72 -> Colonnade Map
Ö Villa Map 72 -> Catacomb Map
Ä Temple Map 73 -> Torture Chamber Map
Ë Arachnid Nest Map 73 -> Waste Pool Map
Ï Strand Map 73 -> Mine Map
Æ Dry Woods Map 73 -> Jungle Valley Map
Œ Colonnade Map 73 -> Labyrinth Map
Ñ Catacomb Map 73 -> Torture Chamber Map
Ÿ Torture Chamber Map 74 -> Cells Map
1 Waste Pool Map 74 -> Canyon Map
2 Mine Map 74 -> Dark Forest
3 Jungle Valley Map 74 -> Dry Peninsula Map
4 Labyrinth Map 74 -> Orchard Map
5 Cells Map 75 -> Underground River Map
6 Canyon Map 75 -> Arid Lake Map
7 Dark Forest Map 75 -> Gorge Map
8 Dry Peninsula Map 75 -> Residence Map
9 Orchard Map 75 -> Underground River Map
0 Underground River Map 76 -> Necropolis Map
? Arid Lake Map 76 -> Plateau Map
! Gorge Map 76 -> Bazaar Map
( Residence Map 76 -> Volcano Map
) Necropolis Map 77 -> Crematorium Map
- Plateau Map 77 -> Precinct Map
/ Bazaar Map 77 -> Academy Map
\ Volcano Map 77 -> Springs Map
| Crematorium Map 78 -> Shipyard Map
= Precinct Map 78 -> Overgrown Ruin Map
* Academy Map 78 -> Village Ruin Map
† Springs Map 78 -> Arsenal Map
‡ Shipyard Map 79 -> Wasteland Map
§ Overgrown Ruin Map 79 -> Courtyard Map
[ Village Ruin Map 79 -> Excavation Map
] Arsenal Map 79 -> Waterways Map
_ Wasteland Map 80 -> Palace Map
~ Courtyard Map 80 -> Shrine Map
{ Excavation Map 80 -> Maze Map
} Waterways Map 80 -> Palace Map
© Palace Map 81 -> Abyss Map
€ Shrine Map 81 -> Abyss Map
< Maze Map 81 -> Colosseum Map
> Vaal Temple Map 81 -> Colosseum Map
µ Abyss Map 82
» Colosseum Map 82


These lines follow this sheme:

Symbol of the map | Name of the map | Level of the map | Map received from combining


Note that the abyss and colosseum map dont combine into higher level ones since they are the highest level.

INPUT:
Your input will be a a string of Symbols which correspond to the map symbols, example AAAEE which would mean 3 x crypt map and 2 x dungeon map.

OUTPUT:
The output will be again a string of symbols which would represent the highest possible combination of the input maps. Any combination of output is allowed as long as it features every map.

EXAMPLES:

INPUT: A
OUTPUT: A

INPUT: AAA
OUTPUT: S

INPUT: AAAEEEIII
OUTPUT: SHR or HRS or RHS or SRH

INPUT: AAAAAAAAAE
OUTPUT: WE or EW

INPUT: »»»»»
OUTPUT: »»»»»


SCORING:
Your score will be calculated through this formula, which is also actualy used in the game to calculate damage reduction:

POINTS = 1000 - (ByteCount / (ByteCount + 1000) * 1000);


BONUS POINTS:

1. If you add runlenght encoding to both the input and output then multiply your points by 1.2, example 3A input instead of AAA. You can omit the standard input if your answer will support this.

2. If your program will allow the actual map names as input/output then multiply your points by 1.5, you can ommit the "map" part of the map name so as a example input "crypt crypt crypt" and output "sewer" is ok. Your script also doesnt need to understand the standard input anymore if you use this method. This method also requires a space between names in both the input and output.

3. If your output string goes from lowest level map to highest then multiply your points by 1.08, maps with the same level dont need to be sorted in any particular way.

You can combine all 3 bonus points.

ANSWER WITH THE MOST POINTS WINS!

• Can we assume that, in the input, the same type of map will be next to each other? For example, in test case 3 we don't have to deal with something like AEIAEIAEI? – Sok Jul 16 '15 at 8:42
• No the input will always be random, i will bumb up the bonus points for that part now that i think about it – Vajura Jul 16 '15 at 8:42
• Find your own way inland, exile! :^P – FryAmTheEggman Jul 17 '15 at 4:07
• If the input is random then how does the runlength bonus work? Can we get inputs like 2AEA for AAEA? Or will it be 3AE? – Fatalize Aug 13 '15 at 12:53
• Huh, I don't get it ._. – OverCoder Aug 13 '15 at 13:02

# Haskell, 306 bytes, points = 766 * 1.2 * 1.08 = 992.343

import Control.Arrow;main=print=<<(\x->unwords.map(\(x,y)->show x++[y]).filter((>0).fst).g=<<(read***head)<$>(lex=<<words x))<$>getLine;g z@(x,y)|x<3=[z]|1<2=maybe[z](\w->(xmod3,y):g(xdiv3,w)).lookup y$words"ASWKÉÄŸ50)|‡_©µ EHFJÁË16?-=§~€µ IRGXÍÏ27!/*[{<» ULPZÜŒ490 TCBÓÖÑŸ NMVK >»">>= \x->zip x$tail x


I could squeeze out a few more bytes should anyone beat me, but for now I'm going to leave it as is.

import Control.Arrow;main=interact$show.(\x->unwords[show a++[b]|(a,b)<-g=<<second head<$>(reads=<<words x),a>0]);g z@(x,y)|x<3=[z]|1<2=maybe[z](\w->(xmod3,y):g(xdiv3,w)).lookup y$words"ASWKÉÄŸ50)|‡_©µ EHFJÁË16?-=§~€µ IRGXÍÏ27!/*[{<» ULPZÜŒ490 TCBÓÖÑŸ NMVK >»">>=(flip zip=<<tail)  I did squeeze out a few more bytes regardless. # Haskell, 248 bytes, points = 801 * 1.2 * 1.08 = 1038.462 main=interact$ \x->unwords[show a++b|(a,b)<-(reads=<<words x)>>=g,a>0];g z@(x,y)|x<3=[z]|1<2=maybe[z](\w->(xmod3,y):g(xdiv3,w))$pure<$>lookup(head y)(zip<*>tail=<<words"ASWKÉÄŸ50)|‡_©µ EHFJÁË16?-=§~€µ IRGXÍÏ27!/*[{<» ULPZÜŒ490 TCBÓÖÑŸ NMVK >»")


I am also going to leave a few tables I made for others to use:

68   AS EH IR OD UL TC NM
69   SW HF RG DY LP CB MV
70   WK FJ GX YQ PZ BÓ VK
71   KÉ JÁ XÍ QÚ ZÜ ÓÖ
72   ÉÄ ÁË ÍÏ ÚÆ ÜŒ ÖÑ
73   ÄŸ Ë1 Ï2 Æ3 Œ4 ÑŸ
74   Ÿ5 16 27 38 49
75   50 6? 7! 8( 90
76   0) ?- !/ (\
77   )| -= /* \†
78   |‡ =§ *[ †]
79   ‡_ §~ [{ ]}
81   ©µ €µ <»
82   µ  µ  »

>»


You read it from top to bottom, two letters at a time (or ignore odd columns). Three A's make a S, Three S-es makes a W and so on. Chains that end simply wrap around to the first column on the next line. No three maps makes a >.

Here are the chains of maps you can make with no repeats:

ASWKÉÄŸ50)|‡_©µ
EHFJÁË16?-=§~€µ
IRGXÍÏ27!/*[{<»
ULPZÜŒ490
TCBÓÖÑŸ
NMVK
>»


## C#, 364 361 bytes, points = 734.754 x 1.08 = 793.534

Might as well get the ball rolling with a big one...

string F(string s){var m=@"AEIOUTNSHRDLCMWFGYPBVKJXQZÓÉÁÍÚÜÖÄËÏÆŒÑŸ1234567890?!()-/\|=*†‡§[]_~{}©€<>µ»";var g=new int[75];foreach(int a in s.Select(c=>m.IndexOf(c)))g[a]++;int i=0;for(;i<73;){g[m.IndexOf(@"SHRDLCMWFGYPBVKJXQZÓKÉÁÍÚÜÖÄËÏÆŒÑŸ1234Ÿ567890?!(0)-/\|=*†‡§[]_~{}©€<©µµ»»"[i])]+=g[i]/3;g[i++]%=3;}return string.Join("",g.Zip(m,(x,l)=>"".PadLeft(x,l)));}


I've yet to think of a clever way of mapping the seemingly random encoded characters to their relative worth, so I've used a brute force method for now.

This implements bonus feature 3 by virtue of the method of grouping, which nets me a cool 58ish points.

Edit: Rewrote output loop into join/zip

# SWI-Prolog, 354 bytes, points = 738.552 * 1.08 = 797.64

a(A,Z):-msort(A,S),b(S,[],B),(msort(B,S),string_codes(Z,S);a(B,Z)).
b(X,R,Z):-(X=[A,A,A|T],nth0(I,AEIOUTNSHRDLCMWFGYPBVKJXQZÓÉÁÍÚÜÖÄËÏÆŒÑŸ1234567890?!()-/\\|=*†‡§[]_~{}©€<>,A),nth0(I,SHRDLCMWFGYPBVKJXQZÓKÉÁÍÚÜÖÄËÏÆŒÑŸ1234Ÿ567890?!(0)-/\\|=*†‡§[]_~{}©€<©µµ»»,B),b(T,[B|R],Z);X=[A|T],b(T,[A|R],Z);Z=R).


Expects inputs as codes strings, for example a(AAAEEEIII,Z). will output Z = "SRH".

I'll see what I can do about the other two bonuses...

# Javascript, 432 bytes, points = 698.32 * 1.08 * 1.2 = 905.02

function g(r){for(var n="AEIOUTNSHRDLCMWFGYPBVKJXQZÓÉÁÍÚÜÖÄËÏÆŒÑŸ1234567890?!()-/|=*†‡§[]_~{}©€<>",t="SHRDLCMWFGYPBVKJXQZÓKÉÁÍÚÜÖÄËÏÆŒÑŸ1234Ÿ567890?!(0)-/|=*†‡§[]_~{}©€<©µµ»»",a=/([^»µ])\1{2}/,c=/\d+/,e=/\d+(.)/,f=0;0!==(f=r.match(c)-0);)r=r.replace(c,Array(f).join(r.match(e)[1]));for(;null!==(f=r.match(a));)r=r.replace(a,t.charAt(n.search(f[1])));return r.split("").sort(function(r,t){return n.indexOf(r)-n.indexOf(t)}).join("")}


# ECMAScript 6, 417 bytes, points = 705.72 * 1.08 * 1.2 = 914.61

## No online minifier version: (last version was passed through a minifier)

let F=s=>{for(var m="AEIOUTNSHRDLCMWFGYPBVKJXQZÓÉÁÍÚÜÖÄËÏÆŒÑŸ1234567890?!()-/\|=*†‡§[]_~{}©€<>",r="SHRDLCMWFGYPBVKJXQZÓKÉÁÍÚÜÖÄËÏÆŒÑŸ1234Ÿ567890?!(0)-/\|=*†‡§[]_~{}©€<©µµ»»",x=/([^»µ])\1{2}/,y=/\d+/,z=/\d+(.)/,p=0;(p=s.match(y)-0)!==0;)s=s.replace(y,Array(p).join(s.match(z)[1]));for(;(p=s.match(x))!==null;)s=s.replace(x,r.charAt(m.search(p[1])));return s.split('').sort((a,b)=>m.indexOf(a)-m.indexOf(b)).join('');};


Run with Babel

Tested with the following inputs:

1. AAA
2. AAAEEEIII
3. 3A3E3I
4. »»»»»
5. 5»

## General solution

Basically using regex whenever possible

var m = "AEIOUTNSHRDLCMWFGYPBVKJXQZÓÉÁÍÚÜÖÄËÏÆŒÑŸ1234567890?!()-/\|=*†‡§[]_~{}©€<>";
var x = /([^»µ])\1{2}/;

while((p=s.match(x))!==null){
s=s.replace(x,r.charAt(m.search(p[1])));
}


Nothing fancy here, just replacing a match for the respective output.

### For the 1.2 Bonus

Regexing the numbers and the following letter, readable code goes like this:

// variable 's' is the input string

var y = /\d+/;
var z = /\d+(.)/;

var p = 0;

while((p=s.match(y)-0) !== 0) {
s=s.replace(y,Array(p).join(s.match(z)[1]));
}


As you can see, s.match(y) - 0, the matched string is subtracted by 0, that's to force a parse int without actually calling parseInt().

Also Array(p).join(s.match(z)[1]) basically joins an array of p empty elements, with the character found in the match, that's an easy way to print a letter (let's say E) p amount of times.

### For the 1.08 Bonus

Sorting algorithm:

s.split('').sort(function(a,b) {
return m.indexOf(a) - m.indexOf(b);
}).join('');

• I don't see how you can possibly get a base score of 999.999 with 432 bytes. I get 698.324 with the given formula. – Fatalize Aug 13 '15 at 18:05
• My bad, I must have typed the formula wrongly, I'll fix it – Christopher Francisco Aug 13 '15 at 18:38

# Javascript (ES6), 389 bytes, points = 719.942 * 1.08 * 1.2 = 933.045

In the lead, at least for now...

a=>{a=a.replace(/(\d)(.)/g,(m,A,B)=>B.repeat(A)),x='AEIOUTNSHRDLCMWFGYPBVKJXQZÓÉÁÍÚÜÖÄËÏÆŒÑŸ1234567890?!()-/\\|=*†‡§[]_~{}©€<>',y='SHRDLCMWFGYPBVKJXQZÓKÉÁÍÚÜÖÄËÏÆŒÑŸ1234Ÿ567890?!(0)-/\\|=*†‡§[]_~{}©€<©µµ»»',s=_=>(a=[...a].sort((a,b)=>x[I='indexOf'](a)-x[I](b)).join);s();for(i=0;i<x.length;i++){a=a.replace(new RegExp([${('\\|'[I](h=x[i])<0?'':'\\')+h}]{3},'g'),y[i]);s()}return a}  Try it here: F=a=>{a=a.replace(/(\d)(.)/g,(m,A,B)=>B.repeat(A)),x='AEIOUTNSHRDLCMWFGYPBVKJXQZÓÉÁÍÚÜÖÄËÏÆŒÑŸ1234567890?!()-/\\|=*†‡§[]_~{}©€<>',y='SHRDLCMWFGYPBVKJXQZÓKÉÁÍÚÜÖÄËÏÆŒÑŸ1234Ÿ567890?!(0)-/\\|=*†‡§[]_~{}©€<©µµ»»',s=_=>(a=[...a].sort((a,b)=>x[I='indexOf'](a)-x[I](b)).join);s();for(i=0;i<x.length;i++){a=a.replace(new RegExp([${('\\|'[I](h=x[i])<0?'':'\\')+h}]{3},'g'),y[i]);s()}return a};

input=document.getElementById("input");
p=document.getElementById("a");
})
<form>Type your text here: <input type="text" id="input" value="3A"/></form>
<p id="a">S</p>
The 1.2 bonus is somewhat tricky in its formatting. If you want to input a regular number, place a 1 before it.
Basically, this scans through every character that has an upgrade (all except µ and »), then finds all sets of three of this character and replaces them with the upgraded char. Sorting after each .replace was the best way to make sure this always works properly, so that was an automatic bonus. The 1.2 bonus was a little harder, but I got it sorted out in 45 bytes. The 1.5 bonus is just not worth it at all, as it requires a ton more encoding and would at least double the length.