Formula One is a complex sport and as with complex sports, strategy is very important.Some teams will manage better strategy than others and those teams will often win the races.

After last weekends' amazing German GP, which saw last years Champion Lewis Hamilton pit 6 times (in comparison, some races just have 1 stop per driver), I was really impressed with all the strategy that was involved by most of the teams. Some really great calls, such as going to soft (from inters) by Racing Point, saw their driver finish 4th which was a rare sight.


Your task will be to suggest what tire configuration should be used for the race.


Here are the 3 available tire types :

All of this data unofficial data, this is unreal data that was made juste for a fun challenge. I tried to keep a little sense in choosing how durable the tires wowuld be, but as I repeat, this is UNOFFICIAL

Name                           Soft   Medium   Hard
Degradation (per character)    15     10       8
Degradation (per corner)       263    161      128
Time delta (per corner) (ms)   0      +30      +45

There is no time delta on the straights so all tire perform the same

A tires life span is calculated by how many COMPLETE laps it can do before dying. It's health starts at 100 000 and will decrease by the degradation value in the above table.


You will be able to change tires by going to the pits but a pit stop will cost you time. That time is measured by the distance between P to P (the length EXCLUDES the Ps on the start/finish straight multipled by 1750 milliseconds.

time for pits = (length between P to P) x 1750 ms

You must just complete the lap on the previous set of tires. So in a way, you are changing them at an imaginary line between the # and the character before it. Tire degradation in the pits are as if you were driving on track.


A corner is where the characters changes (look at exeption bellow)

All ascii characters can be used for the track (except the exceptions bellow that have specific meaning)

This does not count as a corner, it is just a kink. This is just extra info seeing as the drawings are not considered official and just a representation to give users a better idea or to validate an algorithm.

Ex 1

Ex 2

The P does not represent a corner , it is the pit entrance and exit. It still counts in track length though.


The # represents the start/finish line (the start and finish line will be the same for the purposes of simplifying things. They also count in track length. The race will start at an imaginary line between the # and whatever comes before it, so yes, the # will degrade the tires when the race starts. The # is also the first character in the input. You may assume that the last character of the track will be the same as the first character after the start/finish line (#).


The track:

  1. A list/array of all the characters in order
  2. A string with all the characters in order

Bonus. The track map drawing made out of the ascii characters (unofficial as it I won't garantee at this point int time that both the drawing and the string bellow are the same

Number of laps:

  • An integer, however you want to receive it.
Ex.1 ["_P_#_P_||_______||", 250]
Ex.2 ["_","P","_","#","_","P","_","|","|","_","_","_","_","_","_","_","|","|"], 69


The tire strategy with 3 distinct characters to represent the 3 tire compound. Tires can be identified either with letters, numbers, or even words if you want.

You must output all the tires necessary for the race. Tire output must be from softest to hardest compouds.

Ex.1  [S, M, H]
Ex.2  [0, 1]
Ex.3  [Hard]


TL;DR: find the tire combination that optimizes time delta.

You must use all the tire data (constants) and the race data (track and number of laps, this will be your input) to optimize the best tire strategy (output) in order to minimize the time delta.

A time delta of 0 will be the perfect (but impossible) score, where you would run the soft tires (the fastest) the whole race. Thus, you must use a combinations of tires and run them for how many laps you want as long as it is still in the tires life span. Running soft for the whole race is fastest, but each time you change them at the end of a tire's life span, it will raise your time delta, because you must pit.


  • This is code golf so shortest code wins!
  • The rest is almost a free-for-all (just don't hard code the answers in!)


Note, drawings are not offial, it is just for representation.

Also, the output aren't checked by another person then me yet, so if you are doing the challenge and find some errors, please notify me.

1. Circuit de Spa-Francorchamps: (yes I know it looks like a gun, but it isn't gun related, I promise, Google the track if you want):

        _____^^^          ___________________________
 _P_____                                             \___
<_____#_____P                                            |
             |_____________                  ________    |
                            \               /        |   |
                              \            /         |___|
                                \         |   
                                 |        |
                                 |       _| 
                                 |      | 



44 laps per race (according to Wikipedia, Belgian GP 2018)

OUTPUT: [Medium, Medium]

2. Autodromo Nazionale Monza:

\       \
 \        \
  \          \
   \___        \
       \         \____                                
         \            \__________________________
           \                                      \
             \                                    /
               \ _____/___P__#_________P________/



53 laps per race (according to Wikipedia, Italian GP 2018)

OUTPUT : [Soft, Medium]

3. Circuit Gilles Villeneuve:

       ____|    ____
    __/             \___________    
   /    ____#___                _______
  /P___/        |P______________________>



70 laps per race (according to Wikipedia, Canadian GP 2019)

OUTPUT : [Soft, Soft, Medium]

4. Pocono Raceway (not an F1 track, but here to test edge-cases)

             / \
            /    \
           /       \
          /          \
         /             \
        /                \
       /                   \
      /                      \
     /                         \
    /                            \
   /                               \
  /                                  \
 /                                     \



110 laps per race

Number of laps is innacurate, according to USA Today, it is going to be 160 laps for the 2019 Sunday's Gander Outdoors 400, the 21st race in the Monster Energy NASCAR Cup Series. In F1, races are at least 305km, making any race around this raceway around 76 laps.

OUTPUT : [Hard]

  • 1
    \$\begingroup\$ @JonathanAllan Added in Pocono Raceway (not an F1 track but at least a real track. Only 3 corners so minimum tire degradation). I put the number of laps so that it fits exactly with the tire life of Hard tires \$\endgroup\$
    – Dat
    Commented Aug 2, 2019 at 1:23
  • \$\begingroup\$ @Arnaud, Actually, just output the order in order of softest to hardest. Because Running a [Soft, Hard] is slightly different then [Hard, Soft], in the sense that you will not be running the hard to it's fullest extent before changing it \$\endgroup\$
    – Dat
    Commented Aug 2, 2019 at 13:08

3 Answers 3


JavaScript (ES6), 234 bytes

Takes input as (track)(laps), where track is an array of characters. Returns a string with \$0\$ = soft, \$1\$ = medium, \$2\$ = hard.


Try it online!


Jelly, 105 102 bytes


Try it online!

A full program that takes the track as a string as its first argument and the number of laps as its second argument. Returns a list of integers representing 1 for soft, 2 for medium and 3 for hard.


Helper link: calculate pit time from number of tyres needed

³                 | First argument for program (track as Jelly string)
 ;`               | Concatenate to itself
   ẹ”P            | Indices of "P"
      Ḋ           | Dequeue (remove first element)
       I          | Differences between consecutive numbers
        Ḣ         | Head (i.e. difference between indices of the 2nd and 3rd Ps in the concatenated track)
         ’        | Decrease by 1
          ×⁽£ż    | Multiply by 1750
              ×   | Multiply by:
               ’  | - Argument to this link subtracted by 1

Main link: stage 1

ḟ⁾#P                                   | Remove all "#" and "P" from track
    nƝ                                 | Neighbours not equal (will return 1 for every change in symbol)
      S                                | Sum (i.e. number of corners)
       ,L{                             | Pair with length of original track
          ḋ                   ¤        | Dot product with following as a nilad: (Will calculate degradation per lap for each tyre type and also extra time for the corners; works because of the way Jelly vectorises)
                     ¤                 | - Following as a nilad
           “Ðẏ½Ƥ®x‘                    |   - 15, 248, 10, 151, 8, 120
                   s2                  |   - Split into twos [15,248],[10,151],[8,120]
                      Ä                | - Vectorised cumulative sum [15,263],[10,161],[8,128]
                       U               | - Vectorised reverse [263,15],[161,10],[128,8]
                        ż“¡œ-‘         | - Zipped with 0,30,45
                               ȷ5W¤÷   | Divide 100,000 by the first element of each (the degradation), leaving the additonal time per corner alone
                                    Ḟ  | Floor
                                     µ | Start a new monadic link with this as its argument

Main link: stage 2

⁴÷          | Second argument (number of laps) divided by output of stage 1
  Ḣ         | Head (values for soft tyres)
   Ḣ        | Head (laps per tyre for aoft tyres)
    Ċ       | Ceiling (i.e. max number of tyres that might be needed)
     3ṗⱮ    | 3 to the Cartesian power of each number from 1 to the max number of tyres needed
        Ẏ   | Tighten (remove one level of lists)
         ị  | Index into output from stage 1
          µ | Start a new monadic link with this as its argument

Main link: stage 3

                                 )     | For each of the possible tyre combinations:
Z                                      | - Transpose, so we have a list of laps per tyre set and another list of the extra time for corners per lap
           ʋ/                          | - Reduce using following as a dyad:
 ż    Ʋ{                               |   - Zip with following as a monad (applied to the list of laps per tyre set)
  Ä                                    |     - Cumulative sum
   Ż                                   |     - Prepended with zero
    ⁴_                                 |     - Subtracted from the number of laps
        Ṃ€                             |   - Minimum of each
          ż                            |   - Zip with additional time for corners
             >0Ḣ$Ƈ                     | - Filter those where the first number (the number of laps used for those tyres) is greater than zero
                              Ʋ        | - Following as a monad:
                  ẈṪ                   |   - Tail of the lengths (will be 2 if all laps accounted for, 1 if not)
                    ,        Ɗ         |   - Paired with following as a monad:
                     P€                |     - Product of each (additional time for each tyre set from corners for all laps driven)
                           Ʋ           |     - Following as a monad:
                       LÑ              |       - Helper link applied to length (number of tyre sets)
                         +             |       - Plus:
                          S            |         - Sum (of additional times for each tyre set)
                            N          |     - Negated
                                  M    | Indices of maximum
                                   Ḣ   | Head
                                    ḃ3 | Bijective base 3

Python3, 557 bytes

I=lambda t,c:(c+1)%len(t)
F=lambda t,C:t[C]not in{'P','#'}and t[I(t,C)]not in{'P','#'}and t[C]!=t[I(t,C)]
def f(t,l):
 q=[(H,l,[i],0,0)for i,_ in E(T)]
 for h,l,u,r,c in q:
  if l==0:U+=[(u,r)];continue
  if c==0 and h<H:l-=1
   if h<m[0]*W+m[1]*K:
    for i,_ in E(T):q+=[(H,l,u+[i],r+W*1750,I(t,c))]
 return min(U,key=lambda x:x[1])

Try it online!

  • \$\begingroup\$ F=lambda t,C:t[C]not in'P#'and t[I(t,C)]not in'P#'+t[C] ... H,T,U=100000,[[15,263,0],[10,161,30],[8,128,45]],[] ... l-=(c==0)*(h<H) ... K=W=0;C=I(t,c) \$\endgroup\$
    – movatica
    Commented Feb 18 at 17:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.