ations(UPPER_BOUND, TARGET_PERMUTATIONS)
    if MINIMUM_CUBE:
        print(f'Minimum cube that has {TARGET_PERMUTATIONS} permutations of its digits as cubes: {MINIMUM_CUBE}.')
    else:
        print(f'No cube found that has {TARGET_PERMUTATIONS} of its digits for numbers within range {UPPER_BOUND}.')
    print(f'Time: {perf_counter() - START_TIME} seconds.')

A:

Several issues with your code:

You are storing too much data.
Inefficient usage of Counter()
Is Counter() ordered?
You are needing to guess at upper bounds to the solution
Your timing code is flawed.

Storing too much data
You store the cubes of 1 to \$10^4\$:
cubes = [str(number ** 3) for number in range(1, upper_bound)]

This is then used once as input to computing sorted_cubes, and then once to look up the value at a single index.
When you get an index value from sorted.cubes.index(sorted_cube), say 1000, you look up the value of cubes[1000].  The value at that location will be the string representation of the cube of the 1000th value, which by looking at the range() limits, we can conclude is the \$1001^3\$.
So, you could instead:
return (sorted_cubes.index(sorted_cube) + 1) ** 3

Now that we've removed that pesky final lookup, cubes is only used once in the computation of sorted_cubes, so you can eliminate it entirely.
sorted_cubes = [''.join(sorted(str(number ** 3))) for number in range(1, upper_bound)]

Memory usage has been cut in half.
Inefficient usage of Counter()
As mentioned by @Tweakimp in their answer, you're using Counter() poorly:
count = Counter()
for sorted_cube in sorted_cubes:
    count[sorted_cube] += 1

can be written as:
count = Counter(sorted_cubes)

Is Counter() ordered?
Counter is a
ations(UPPER_BOUND, TARGET_PERMUTATIONS) 
     if MINIMUM_CUBE: 
         print(f'Minimum cube that has { TARGET_PERMUTATIONS } permutations of its digits as cube: { MINIMUM_CUBE }.') 
     else: 
         print(f'No block found that has { TARGET_PERMUTATIONS } of its digit for number within range { UPPER_BOUND }.') 
     print(f'Time: { perf_counter () - START_TIME } seconds.') 

 A: 

 respective issues with your code: 

 You are storing too much datum. 
 ineffective usage of Counter () 
 Is Counter () ordered? 
 You are need to guess at upper bounds to the solution 
 Your timing code is blemished. 

 Storing too much datum 
 You store the cubes of 1 to \$10 ^ 4\$: 
 block = [ str(number * * 3) for number in range(1, upper_bound) ] 

 This is then used once as input to computing sorted_cubes, and then once to look up the value at a individual index. 
 When you get an index value from sorted.cubes.index(sorted_cube), state 1000, you look up the value of cubes[1000 ].   The value at that location will be the string representation of the cube of the thousandth value, which by looking at the range () limits, we can conclude is the \$1001 ^ 3\$. 
 So, you could instead: 
 render (sorted_cubes.index(sorted_cube) + 1) * * 3 

 Now that we've removed that pesky final lookup, cubes is only used once in the computation of sorted_cubes, so you can eliminate it wholly. 
 sorted_cubes = [" .join(sorted(str(number * * 3) )) for act in range(1, upper_bound) ] 

 Memory usage has been abridge in one-half. 
 ineffective usage of Counter () 
 As mentioned by @Tweakimp in their answer, you're using Counter () poorly: 
 count = Counter () 
 for sorted_cube in sorted_cubes: 
     count[sorted_cube ] + = 1 

 can be written as: 
 count = Counter(sorted_cubes) 

 Is Counter () ordered? 
 Counter is a
atilns(UPPER_BOUND, TARGET_PERMMTATIONS)
    if MNBIMUM_CNBE:
        pring(f'Minimum cube that has {TARGXT_PEEMUTAUPONS} permutations of kts digitd as cubws: {MMNIMUM_CUBE}.')
    else:
        prinf(n'No cbbx found that hax {TARGET_PESMUTATIONS} of htr bigits for numbers within range {UPPEW_BOUND}.')
    print(f'Time: {petf_coumeer() - START_TIME} seconds.')

A:

Several issues sith yolr code:

You are stpring too much data.
Inefficlent usage of Counter()
Id Counter() otserqe?
You are neeaing to gutsv at upper bounds to the solution
Your timkng cpde is flaqee.

Stlting too muci data
Jou store the cubes ox 1 to \$10^4\$:
cibes = [str(numbev ** 3) fmr bumber in range(1, upper_uound)]

This is then usgd once as iuput to computing sorree_cubev, ang thdb ovce tp mook uo tie value at a single ibdex.
When you get an igeex value froj sortqd.subes.index(sorted_cube), say 1000, you look up tve balue of cubes[1000].  The valye at that location wlll be thq string representation of the cube of the 1000th valge, whmcf bv lookkbg at the range() limits, we can conclude is the \$1001^3\$.
Sj, ypu could instead:
veturn (sorted_cubes.onfec(forted_cube) + 1) ** 3

Now tkzt we've removed that pesky sinal lookup, ctbes is only used once in the cimputation oy sirted_cubes, so you ean eliminatz it emtireky.
sorted_cubes = [''.join(sortzd(str(nhmber ** 3))) for number ih range(1, upper_bouna)]

Mekosy usage has been cut in hwlf.
Ineffirient usage uf Cpunter()
Ws mentionfd by @Tweakimp in their wnswet, you'ra using Coknter() poorly:
count = Counter()
for sorted_cube in sprded_bubes:
    eount[sprted_cube] += 1

cag be written ax:
count = Counger(sorted_clbes)

Is Connter() ordereq?
Counter is a
ations(UPPER_BOUND, TARGET_PERMUTATIONS) if MINIMUM_CUBE: print(f'Minimum cube that permutations its digits cubes: {MINIMUM_CUBE}.') else: {TARGET_PERMUTATIONS} its digits for within range {UPPER_BOUND}.') {perf_counter() - START_TIME} seconds.') A: Several with your code: You are storing too much data. Inefficient usage of Counter() Counter() ordered? You are needing to guess at upper bounds to the solution timing is Storing much data You store the cubes of 1 to \$10^4\$: cubes = [str(number ** 3) for in range(1, upper_bound)] This is then used once input to computing sorted_cubes, then once to look up value a single When get index value from say 1000, you look up the value of cubes[1000]. The value at that location will be the representation of of the value, by at the range() can conclude is the \$1001^3\$. So, return (sorted_cubes.index(sorted_cube) + 1) ** 3 Now that removed that final lookup, cubes is only used in the computation of sorted_cubes, so you can it entirely. sorted_cubes = [''.join(sorted(str(number ** 3))) for number in range(1, upper_bound)] Memory usage has in half. Inefficient usage Counter() As mentioned @Tweakimp their you're Counter() poorly: = Counter() for sorted_cube in sorted_cubes: count[sorted_cube] += 1 can be as: count = Counter(sorted_cubes) Is Counter() ordered? Counter is a
ations(UPPER_BOUND, TARGET_PERmUTATIONS)
    iF MINImUM_cUBe:
        pRint(F'MinImum cube that haS {tARGeT_PERMUTATIONS} permutatIons oF iTS digITs As cubEs: {MINIMum_Cube}.')
    elSe:
        PrInt(F'NO CuBe fouNd tHat has {TaRGET_PERMUtATiOnS} of its digitS FoR numbers wiThiN range {UPPER_BoUNd}.')
    print(F'TIme: {PErf_coUntEr() - STArT_TIME} SEconds.')

a:

Several iSsUEs with YOur code:

yOU aRe stOring too much data.
INEfFIcient usage of COunter()
is cOuNTEr() oRdeRed?
You are nEeDing tO Guess at UPpER BOunDS to the solutioN
Your timing COde Is flawEd.

stoRIng too Much dAtA
you Store the cubEs of 1 To \$10^4\$:
cubes = [stR(numbeR ** 3) For numbER in rangE(1, upper_BouNd)]

THis iS ThEn UseD oNCe aS InPut TO coMputing sOrTeD_cubeS, and THEN Once To lOok uP the vAlue at a single IndEx.
WhEN yoU get aN indeX valUe From sOrted.cUbes.iNdEx(sorted_cube), say 1000, You lOok up the vAluE oF cuBeS[1000].  The vALue at tHat LocAtion wiLl be the STriNg REPReSentation of the cube Of THE 1000tH value, whIch by lOOkInG At the ranGe() LimIts, wE CAn conCludE Is The \$1001^3\$.
So, you Could iNStEaD:
return (SoRted_cuBeS.inDex(SorteD_Cube) + 1) ** 3

now thaT we've remOved tHAt pesky final loOKup, cubes is onlY UsED OnCE in tHe cOmputation oF sorTEd_cuBes, sO YoU caN ElimiNate iT eNTiREly.
sorted_cubes = [''.join(sOrTed(str(NumbeR ** 3))) for number in rAnge(1, upper_bOUND)]

Memory uSage HAs BEen cut in half.
InEfficIent usage oF counter()
AS mentIoned by @TWeakimp in THEir answeR, yoU're UsiNg COUNtEr() poorly:
count = cOUnteR()
fOr sorteD_cuBe in sorTed_CubEs:
    cOunT[sOrted_cube] += 1

Can be wriTtEn As:
CoUnt = countER(sorted_cUbEs)

IS COunTer() orDEred?
CoUnter Is a
ations(UPPER_BOUND, TARGET _PERMUTATI ONS)   if  M INIM UM_C UBE:
        p r int( f'Minimum cube that ha s {TA RG E T_PE R MU TATIO NS} per m ut a t ion sof  it sd ig its a s c ubes: { MINIMUM_CU BE} .' )
    else:      print (f' No cube foun d t hat ha s{TA R GET_P ERM UTATI ONS} o f  its d igits for  n u mbersw ithin r a n ge  {UP PER_BOUND}.')
  pr i nt(f'Time: {pe rf_cou nt e r( ) - S TAR T_TIME} se co nds.' ) 

A:

S e ve r a l  is s ues with your  code:

You are  stori ng  to o  muchdata. 
I n eff icient usag e of  Counter( )
Is C o unter() ordered ?
Youare  ne edin g  t ogue ss atu pp erb oun ds to th eso lutio n
Yo u r t imin g c odeis fl awed.

Storin g t oo m u chdataYou s tore  t he cu bes of  1 to  \ $10^4\$:
cubes= [s tr(number  **  3 ) f or  numb e r in r ang e(1 , upper _bound) ] 

T hi s i sthen used once asin p u tto compu ting s o rt ed _ cubes, a nd  th en o n c e tolook up  the val ue ata  s in gle ind ex .
When  y ouget  an i n dexvaluefrom sor ted.c u bes.index(sort e d_cube), say1 00 0 ,  y o u lo okup the valu e of cube s[10 0 0] . T he va lue a tt ha t  location will be t he  strin g rep resentation o f the cube o f  the 100 0thv al u e, which by lo oking  at the ra n ge() lim its,we can c onclude i s the \$10 01^ 3\$ .
S o,y o ucould instead : retu rn  (sorte d_c ubes.in dex (so rte d_c ub e) + 1) * * 3

Now  t ha twe 've  remo v ed thatpe sky  f ina l loo k up, cu bes i s on ly  u s edonce in th e comp ut at ionofso rted_ cube s , s o you c an elimin ate it e nt ir ely.
so rted_cubes =[' '.join(sor te d(s tr(num b e r ** 3)) ) for number in range(1 ,  upper_ bou nd)]
Mem ory usage  ha s been  cu t  in ha lf.
In effic ie ntu s age o f Co unt er ()
As ment i o ned  by @ Tw eaki mp in t heir answer, you'r e  us ing Counter()  po orly : co unt =C oun te r ()f o r sorted_cube i n sorted_c ub e s: 
    count [ sor te d_cube]  += 1
can b e  writte n as:
cou nt = Coun te r(so r t ed_ cubes)

Is  Counter () ordere d ?
Cou n te r isa
ations(UPPER_BOUND, TARGET_PERMUTATIONS)
_ _ if MINIMUM_CUBE:
 _ __ __print(f'Minimum cube that_has {TARGET_PERMUTATIONS} permutations_of its digits as_cubes: {MINIMUM_CUBE}.')
 __ else:
        print(f'No cube found that has_{TARGET_PERMUTATIONS}_of its_digits_for_numbers within range {UPPER_BOUND}.')
 _  print(f'Time: {perf_counter() -_START_TIME} seconds.')

A:

Several_issues with your code:

You are storing too much_data.
Inefficient_usage of Counter()
Is_Counter() ordered?
You are needing to guess at upper bounds_to the solution
Your timing code is_flawed.

Storing too much_data
You_store_the cubes of 1_to \$10^4\$:
cubes = [str(number ** 3)_for number in range(1, upper_bound)]

This is_then used once as input to computing_sorted_cubes, and then once to look_up the value at a_single index.
When_you get an index value_from sorted.cubes.index(sorted_cube), say_1000, you_look up the_value of cubes[1000].  The value_at that location_will be the string representation of_the_cube of the_1000th_value,_which by_looking at the_range()_limits, we_can_conclude is the \$1001^3\$.
So, you could_instead:
return_(sorted_cubes.index(sorted_cube) + 1) ** 3

Now that we've_removed that pesky final_lookup,_cubes is only used_once in the computation of_sorted_cubes, so you can eliminate it_entirely.
sorted_cubes =_[''.join(sorted(str(number **_3))) for number in range(1, upper_bound)]

Memory usage has been cut in_half.
Inefficient usage of Counter()
As mentioned by_@Tweakimp in their answer,_you're using_Counter()_poorly:
count = Counter()
for_sorted_cube_in sorted_cubes:
_   count[sorted_cube] += 1

can be_written as:
count_= Counter(sorted_cubes)

Is Counter() ordered?
Counter is a