Skip to content

Instantly share code, notes, and snippets.

@Butanium
Created February 1, 2021 20:31
Show Gist options
  • Save Butanium/e294469ffbd680cea1a80714693c680e to your computer and use it in GitHub Desktop.
Save Butanium/e294469ffbd680cea1a80714693c680e to your computer and use it in GitHub Desktop.
codinGame fall challenge 2020
import sys
import math
import numpy as np
REST = "REST"
WAIT = "WAIT"
# Auto-generated code below aims at helping you parse
# the standard input according to the problem statement.
class Action:
def __init__(self, inp):
self.id = int(inp[0]) # the unique ID of this spell or recipe
self.type = inp[1] # in the first league: BREW; later: CAST, OPPONENT_CAST, LEARN, BREW
self.deltas = list(map(int, inp[2:6])) # tier-0 ingredient change
self.price = int(inp[6]) # the price in rupees if this is a potion
self.tome_index = int(inp[7]) # in the first two leagues: always 0; later: the index in the tome if this is a
# tome spell, equal to the read-ahead tax; For brews, this is the value of the current urgency bonus
self.tax_count = int(inp[8]) # in the first two leagues: always 0; later: the amount of taxed tier-0
# ingredients you gain from learning this spell; For brews, this is how many times
# you can still gain an urgency bonus
self.castable = inp[9] != "0" # in the first league: always 0; later: 1 if this is a castable player spell
self.repeatable = inp[10] != "0" # for the first two leagues: always 0; later: 1 if this is a
# repeatable player spell
debug(str(self.id) + " : " + str(self.deltas))
def debug(message):
print(message, file=sys.stderr, flush=True)
class Witch:
def __init__(self, inp):
self.inventory = inp[:-1:]
self.score = inp[-1]
def is_doable(action: Action, inv, deltas=()):
if not deltas:
for i, delta in enumerate(action.deltas):
debug("need {} and have {} ingredient {}".format(-delta, inv[i], i))
if delta >= 0:
continue
if -delta > inv[i]:
return 0
debug(action.id)
return 1
else:
new_inv = np.array(deltas) + np.array(inv)
return is_doable(action, new_inv)
# game loop
while True:
action_count = int(input()) # the number of spells and recipes in play
actions = []
for i in range(action_count):
inputs = input().split()
actions.append(Action(inputs))
witches = []
for i in range(2):
witches.append(Witch([int(j) for j in input().split()]))
nd_potions = []
d_potions = []
max_price = 0
best_pot_id = False
for potion in actions:
if potion.type != "BREW":
continue
if is_doable(potion, witches[0].inventory):
d_potions.append(potion)
if potion.price > max_price:
best_pot_id, max_price = potion.id, potion.price
else:
nd_potions.append(potion)
# in the first league: BREW <id> | WAIT; later: BREW <id> | CAST <id> [<times>] | LEARN <id> | REST | WAIT
if max_price:
print("BREW " + str(best_pot_id))
continue
c_spell_count = 0
doable_spells = []
spells = []
for spell in actions:
if spell.id != "SPELL":
continue
spells.append(spell)
if is_doable(spell, witches[0].inventory):
doable_spells.append(spell)
if spell.castable:
c_spell_count += 1
best_spell = 0
max_price = 0
for spell in doable_spells:
for potion in nd_potions:
if is_doable(potion, witches[0].inventory, spell.deltas):
if potion.price > max_price:
max_price, best_spell = potion.price, spell
if potion.price == max_price:
if spell.castable and not best_spell.castable:
best_spell = spell
if max_price:
if best_spell.castable:
print("CAST " + str(best_spell.id))
continue
else:
print(REST)
continue
else:
if c_spell_count != 4:
print(REST)
else:
print(WAIT)
open Array;;
module Toolbox = struct
let (+=) i v = i:= !i+v
let (+=.) i v = i:= !i +. v
let rec contains l e = match l with
|x::xs -> if e = x then true else contains xs e
|[] -> false
let (@@) e l = contains l e
let (+++) a b = let m = min (Array.length a) (Array.length b)
in let l = Array.make m 0 in
for k = 0 to m-1 do
l.(k) <- (a.(k) + b.(k));
done;
l
end;;
open Toolbox;;
type poids = Inf | P of int
let (++) a b = match a,b with
|P(a),P(b) -> P(a+b)
|_ -> Inf
let (>>) a b = match a,b with
|P(a), P(b) -> a > b
|Inf, _ -> true
|_ -> false
let (++=) a b = a := !a ++ b;;
class action (actionid:int) (actiontype:string) (delta0:int) delta1 delta2 delta3 (price:int) (tomeindex:int) (taxcount:int) (castable:bool) (repeatable:bool)
=
object (self)
val id = actionid
val atype = actiontype
val delta = [|delta0; delta1; delta2; delta3|]
val price = price
val tomeindex = tomeindex
val taxcount = taxcount
val castable = castable
val repeatable = repeatable
method id = id
method atype = atype
method delta = delta
method price = price
method tomeindex = tomeindex
method taxcount = taxcount
method castable = castable
method repeatable = repeatable
end;;
class witch inv0 inv1 inv2 inv3 score=
object (self)
val inventory = [|inv0;inv1;inv2;inv3|]
val score = score
method inventory = inventory
method score = score
end;;
(* Auto-generated code below aims at helping you parse *)
(* the standard input according to the problem statement. *)
let rec getGains spells output = match spells with
|x::xs ->
for i = 0 to 3 do
if x#deltas.(i) > 0 then output.(i) <- x::output.(i);
done;
getGains xs;
|[] -> ();;
let getMissingsI p inv =
let r = make 4 0 and t = ref true in
for i = 0 to 3 do
let d = p.(i) + inv.(i) in
r.(i) <- d;
if d < 0 then t := false;
done;
r, !t;;
let getLen potion inventory gains maxDepth=
let fut_inv, t = getMissingsI potion inventory in if t then 0 else begin
let rec aux inv len oldInvs path =
let i = ref 0 in
while !i < 4 and inv.(!i) > 0 do
i += 1;
done;
if !i = 3 then len, path else begin if len >= maxDepth then Inf, path else begin
let tempLen = ref P 0 and oInv = inv::oldInvs and newPath = ref [] in
for k = 0 to 3 do let i = 3-k in
if inv.(i) < 0 then begin
let rec crossGains g = match g with
|x::xs -> let aux (inv+++x#deltas)
for i = 0 to (length gains) - 1 do
nL, nP = aux (inv +++ gains.(i)#deltas)
(*todo: start tree search *)
(* game loop *)
while true do
let actioncount = int_of_string (input_line stdin) (* the number of spells and recipes in play *)
in let actions = make actioncount (new action 0 0 0 0 0 0 0 0 0 0 0) and actionListR = ref [] in
for i = 0 to actioncount - 1 do
(* actionid: the unique ID of this spell or recipe *)
(* actiontype: in the first league: BREW; later: CAST, OPPONENT_CAST, LEARN, BREW *)
(* delta0: tier-0 ingredient change *)
(* delta1: tier-1 ingredient change *)
(* delta2: tier-2 ingredient change *)
(* delta3: tier-3 ingredient change *)
(* price: the price in rupees if this is a potion *)
(* tomeindex: in the first two leagues: always 0; later: the index in the tome if this is a tome spell, equal to the read-ahead tax; For brews, this is the value of the current urgency bonus *)
(* taxcount: in the first two leagues: always 0; later: the amount of taxed tier-0 ingredients you gain from learning this spell; For brews, this is how many times you can still gain an urgency bonus *)
(* castable: in the first league: always 0; later: 1 if this is a castable player spell *)
(* repeatable: for the first two leagues: always 0; later: 1 if this is a repeatable player spell *)
let actionid, actiontype, delta0, delta1, delta2, delta3, price, tomeindex, taxcount, castable, repeatable = Scanf.sscanf (input_line stdin) " %d %s %d %d %d %d %d %d %d %d %d" (fun actionid actiontype delta0 delta1 delta2 delta3 price tomeindex taxcount castable repeatable -> (actionid, actiontype, delta0, delta1, delta2, delta3, price, tomeindex, taxcount, castable = 1, repeatable = 1)) in
in let a = (new action actionid actiontype delta0 delta1
delta2 delta3 price tomeindex taxcount castable repeatable) in
actions.(i) <- a; l:= a:: !l;
done;
let witches = make 2 (new witch 0 0 0 0 0);
for i = 0 to 1 do
(* inv0: tier-0 ingredients in inventory *)
(* score: amount of rupees *)
let inv0, inv1, inv2, inv3, score = Scanf.sscanf (input_line stdin) " %d %d %d %d %d" (fun inv0 inv1 inv2 inv3 score -> (inv0, inv1, inv2, inv3, score)) in
witches.(i) <- (new witch inv0 inv1 inv2 inv3 score);
done;
let spellList = let rec isSpell l = match l with
|x::xs -> let t = (isSpell xs) in if x#atype = "CAST" then x::t else t
|[] -> []; in
isSpell !actionListR;;
for i = 0 to actioncount - 1 do
let a = actions.(i) in
if a#atype = "CAST" then
spellList
let myInv = witches.(0)#inventory in
for i=0 to actioncount - 1 do
(* Write an action using print_endline *)
(* To debug: prerr_endline "Debug message"; *)
(* in the first league: BREW <id> | WAIT; later: BREW <id> | CAST <id> [<times>] | LEARN <id> | REST | WAIT *)
print_endline "BREW 0";
();
done;;
open Array;;
class c (d:int array) (i:int) =
object(self)
val deltas = d
val id = i
method deltas = deltas
method id = id
method print = print_int(id); print_string(" : ");
print_arr(deltas);
end;;
let print_arr t = print_string("[");
for i=0 to (length t) - 1 do
print_int(t.(i)); print_string(", ");
done;print_string("]");;
let spelList = [(new c [|1;(-3);0;0|] 0);
(new c [|(-2);0;1;1|] 1); (new c [|0;(-3);2;0|]) 2];;
let rec print_clist l = match l with
|x::xs -> print_int(x#id);print_string(" ; "); print_clist xs;
|[] -> ();;
let gainList = make 4 [];;
let rec getGains spells = match spells with
|x::xs ->
for i = 0 to 3 do
if x#deltas.(i) > 0 then begin
gainList.(i) <- x::gainList.(i);
print_int(x#id); print_string(" has "); print_int(i);
print_newline(); end
done;
getGains xs;
|[] -> (); in
getGains spelList;;
for i = 0 to 3 do
print_clist gainList.(i);
print_newline();
done;;
type poids = Inf | P of int
let (++) a b = match a,b with
|P(a),P(b) -> P(a+b)
|_ -> Inf
let (>>) a b = match a,b with
|P(a), P(b) -> P(a) > P(b)
|Inf, _ -> true
|_ -> false
let (++=) a b = a := !a ++ b;;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment