<commit_before>-- module Weight.PlateOrder where
 module Main where

import qualified Data.List as L
import Control.Monad
import Data.Set as S
import Data.Function (on)
import Control.Monad (sequence)

data Plate = P45 | P25 | P10 | P5 | P2p5 deriving (Eq, Ord, Show)

type Lift = [Plate]
type Workout = [Lift]

squats   = [P45,P45,P5]
gmorning = [P45,P25,P10,P5]
shrugs   = [P45,P25,P10,P5,P2p5]
bench    = [P45,P10]
bentrow  = [P45,P25,P5]
overhead = [P10,P10,P2p5]
curls    = [P10,P5]
triceps  = [P10,P2p5]

main =  print $ blah [] testWorkout
    where
      blah _ [] = []
      blah last stuff = do
        let this = head $ optimalPlateOrder last stuff
        this:blah this (tail stuff)

testWorkout :: Workout
testWorkout = [squats, gmorning, shrugs, bench, bentrow, overhead, curls, triceps]

complexity :: Workout -> Integer
complexity = product . L.map (fromIntegral . L.length)


pcost :: Plate -> Int
pcost P45  = 22
pcost P25  = 17
pcost P10  = 13
pcost P5   = 12
pcost P2p5 = 10


{-
desireable :: Lift -> Bool
-- desireable (P45:P45:P45:P45:xs) = True  These are way out of my range, no point in checking
-- desireable (P45:P45:P45:P45:P45:xs) = True
-- desireable (_:_:P45:P45:_) = False
-- desireable (_:_:_:P45:P45:_) = False
desireable _ = True
-}


-- Prepend the current state of the bar to all possible workouts that spring from it.
-- Limit to 4 workouts to ease computation.
optimalPlateOrder :: Lift -> Workout -> Workout
optimalPlateOrder initialLift = minWorkout . (L.map (initialLift :)) . allPossibleWorkouts . take 4
  where
    minWorkout :: [Workout] -> Workout
    minWorkout xs = tail . snd . L.minimumBy (compare `on` fst) . zip (L.map wCost xs) $ xs

-- Every possible combination of plate orderings given an initial set of plates per exercise.
allPossibleWorkouts :: Workout -> [Workout]
allPossibleWorkouts = sequence . L.map combinations
  where
    combinations :: Ord a => [a] -> [[a]]
    combinations = L.nub . L.permutations

-- Cost of switching plates in a workout from beginning to end.
wCost :: Workout -> Int
wCost w = case w of
  []       -> 0
  (x:y:xs) -> lCost x y + wCost (y:xs)
  _        -> 0
  where
    lCost :: Lift -> Lift -> Int<commit_msg>Putting back in desirability filter in case I ever need it.<commit_after>-- module Weight.PlateOrder where
 module Main where

import qualified Data.List as L
import Control.Monad
import Data.Set as S
import Data.Function (on)
import Control.Monad (sequence)

data Plate = P45 | P25 | P10 | P5 | P2p5 deriving (Eq, Ord, Show)

type Lift = [Plate]
type Workout = [Lift]

squats   = [P45,P45,P5]
gmorning = [P45,P25,P10,P5]
shrugs   = [P45,P25,P10,P5,P2p5]
bench    = [P45,P10]
bentrow  = [P45,P25,P5]
overhead = [P10,P10,P2p5]
curls    = [P10,P5]
triceps  = [P10,P2p5]

main =  print $ blah [] testWorkout
    where
      blah _ [] = []
      blah last stuff = do
        let this = head $ optimalPlateOrder last stuff
        this:blah this (tail stuff)

testWorkout :: Workout
testWorkout = [squats, gmorning, shrugs, bench, bentrow, overhead, curls, triceps]

complexity :: Workout -> Integer
complexity = product . L.map (fromIntegral . L.length)


pcost :: Plate -> Int
pcost P45  = 22
pcost P25  = 17
pcost P10  = 13
pcost P5   = 12
pcost P2p5 = 10


desireable :: Lift -> Bool
-- desireable (P45:P45:P45:P45:xs) = True  These are way out of my range, no point in checking
-- desireable (P45:P45:P45:P45:P45:xs) = True
-- desireable (_:_:P45:P45:_) = False
-- desireable (_:_:_:P45:P45:_) = False
desireable _ = True


-- Prepend the current state of the bar to all possible workouts that spring from it.
-- Limit to 4 workouts to ease computation.
optimalPlateOrder :: Lift -> Workout -> Workout
optimalPlateOrder initialLift = minWorkout . (L.map (initialLift :)) . L.map (L.filter desireable) . allPossibleWorkouts . take 4
  where
    minWorkout :: [Workout] -> Workout
    minWorkout xs = tail . snd . L.minimumBy (compare `on` fst) . zip (L.map wCost xs) $ xs

-- Every possible combination of plate orderings given an initial set of plates per exercise.
allPossibleWorkouts :: Workout -> [Workout]
allPossibleWorkouts = sequence . L.map combinations
  where
    combinations :: Ord a => [a] -> [[a]]
    combinations = L.nub . L.permutations

-- Cost of switching plates in a workout from beginning to end.
wCost :: Workout -> Int
wCost w = case w of
  []       -> 0
  (x:y:xs) -> lCost x y + wCost (y:xs)
  _        -> 0
  where
    lCost :: Lift -> Lift -> Int
{'fraction_non_alphanumeric': 0.11835640911121036, 'fraction_numerical': 0.04510942384993301, 'mean_word_length': 3.237464522232734, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4398673', 'n_tokens_mistral': 1764, 'n_tokens_neox': 1616, 'n_words': 522}