# Shortest digid-app GetPercentageRounds function

## Context

So the Dutch "Ministerie van Binnenlandse Zaken en Koninkrijksrelaties" (NL) - "Ministry of the Interior and Kingdom Relations" (EN) recently released the source code of their digid-app.

They have some goofy code in there, which led to mockery and memes on reddit

Source code of the offending method can be found here. Here's a copy:

private static string GetPercentageRounds(double percentage)
{
if (percentage == 0)
return "⚪⚪⚪⚪⚪⚪⚪⚪⚪⚪";
if (percentage > 0.0 && percentage <= 0.1)
return "🔵⚪⚪⚪⚪⚪⚪⚪⚪⚪";
if (percentage > 0.1 && percentage <= 0.2)
return "🔵🔵⚪⚪⚪⚪⚪⚪⚪⚪";
if (percentage > 0.2 && percentage <= 0.3)
return "🔵🔵🔵⚪⚪⚪⚪⚪⚪⚪";
if (percentage > 0.3 && percentage <= 0.4)
return "🔵🔵🔵🔵⚪⚪⚪⚪⚪⚪";
if (percentage > 0.4 && percentage <= 0.5)
return "🔵🔵🔵🔵🔵⚪⚪⚪⚪⚪";
if (percentage > 0.5 && percentage <= 0.6)
return "🔵🔵🔵🔵🔵🔵⚪⚪⚪⚪";
if (percentage > 0.6 && percentage <= 0.7)
return "🔵🔵🔵🔵🔵🔵🔵⚪⚪⚪";
if (percentage > 0.7 && percentage <= 0.8)
return "🔵🔵🔵🔵🔵🔵🔵🔵⚪⚪";
if (percentage > 0.8 && percentage <= 0.9)
return "🔵🔵🔵🔵🔵🔵🔵🔵🔵⚪";

return "🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵";
}


## Try it online:

https://dotnetfiddle.net/aMEUAM

## Challenge

Write code in any language as short as possible to replicate the above function

## Rule clarification

• You must exactly match the input and output of the original function. Substituting the ball characters with something else is not allowed.
• You must stick to the functions original boundaries. Meaning if the input is something unexpected like -1 or 42 you must still return the same result as the original function.
• May you substitute the characters of the circles? E.g. replacing 🔵 with x and ⚪ with o or something like that? Jan 19 at 22:13
• It needs to be made clearer that values not in the range [0, 1] need to return a full bar of 🔵 Jan 19 at 22:27
• Yes, please add some test cases that include 0, −0.1, 0.95, 1.0, and 1.1
Jan 19 at 22:28
• Nice try, the Dutch government. You can't outsource your coding needs to stack exchange. Jan 19 at 22:35
• The original code isn't actually bad though, it's actually very readable Jan 20 at 7:08

# JavaScript (Node.js), 53 bytes

f=(n,i=10)=>i?f(n,--i)+(n>=0&n<=i/10?"⚪":"🔵"):''


Try it online!

Need n>=0 to handle NaN

# Scratch, 172 166 142 bytes

This program outputs to a global variable o which is automatically displayed and assumes that the i variable is initialized at 0 and that the procedure will only be run once1.

define(n
set[o v]to(
set[a v]to[🔵
repeat(10
change[i v]by(1
if<<(i)>((n)*(10))>and<(-.01)<(n)>>then
set[a v]to[⚪
end
set[o v]to(join(o)(a


Try it on Scratch!

## Scratch, 116 bytes

This solution is technically invalid because it replaces the emojis with the characters "x" and "_". Unfortunately, this method cannot use emojis due to the way strings seem to work in Scratch, as getting the character at a certain index of a string doesn't work for unicode chars. I just wanted to add this since I think it's really cool.

define(n
set[o v]to(
repeat(10
change[i v]by(1
set[o v]to(join(o)(letter((1)+<<(i)>((n)*(10))>and<(-.01)<(n)>>)of[x_


Try it on Scratch!

1For testing purposes, the procedure is run many times in the scratch link, so o is pushed to an array of test results at the end of each call.

• I thought you had to "say" the output... Jan 24 at 12:35
• Also note that the set blocks are in the format set[var v]to() Jan 24 at 12:40
• @UndoneStudios set[var v]to() doesn't produce the correct result in Scratchblocks, while set(v)to() does. Not sure about the "say" thing, I can change it if that's necessary Jan 24 at 21:47
• See this: i.stack.imgur.com/ioudR.png Jan 25 at 7:54
• @Jacob feel free to make a post in the default IO methods post linked above to suggest that Jan 25 at 14:43

# Type System (TypeScript 4.9.4) - 243 188 Bytes

Now they can validate their function with type safety!

• 56 Bytes thanks to @ASCII-only

• 8 Bytes thanks to @ASCII-only

• 114 Bytes only by @ASCII-only (without rounding)

type H<N,C=[],E={length:N},I='🔵',L=C['length'],D=(${N}extends${}e-${}?'0.0':${N}.0)extends0.${L}.0|0.${E['length']}${string}?'⚪':I>=${D}${L extends 9?'':H<N,[...C,0],C,D>}  Example usage: type ProgressBarZero = H<0> type ProgressBarHalf = H<0.5> type ProgressBarFull = H<1>  (Original) Un-golfed Version: type LoadingBar< // N is a given number N extends number, // AddOne is used to add 1 to a number since we can't use addition [0]=1, [1]=2, [9]=10 etc. AddOne extends number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], // Progress is calculated by checking if N is 0 if so return 0, otherwise cast to string and extract first digit after 0.(M)(R...) // and cast to a number along with anything else after R. If R is an empty string '' then we can just return M since this means // it must be .(1)(0), .(2)(0), .(3)(0), etc. otherwise we use M to index V to add one. Progress = N extends 0 ? 0 : ${N} extends 0.${infer M extends number}${infer R} ? R extends '' ? M : AddOne[M] : 10,
// ArrayCounter is an empty tuple which is used to count the iterations by tracking the length and appending
// elements recursively.
ArrayCounter extends any[] = [],
// IsLoading is a cached flag to help denote when to display ⚪ or 🔵 since we can only check for equality and not less than
// or greater than we need to be able to keep track of when we are finished showing the percent loaded.
// OutputString is our output string which we return at the end.
OutputString extends string = '',
// Length tracks the length of A each pass.
Length extends number = ArrayCounter['length'],
// Check if we have loaded all the 🔵 elements by checking if our Length is equal to our Progress
// Symbol is which string to display and in order to check for "never" we need to compare [never] inside a tuple
// otherwise it becomes distributive, also [never] = [0]
Symbol extends string = [CheckIsLoaded] extends [0] ? '⚪' : '🔵'
> =
// Here is the logic portion: if our Length is 10 we are finished and return the OutputString
Length extends 10 ?  OutputString :
// Otherwise call recursively adding a new element to ArrayCounter each time to keep of the iterations
// we can only keep track of the tuple ArrayCounter'ss length and not strings.
LoadingBar<N, AddOne, Progress, [...ArrayCounter, Symbol], CheckIsLoaded, ${OutputString}${Symbol}>


Try it on the TypeScript playground!

• I'm a big fan of TS types in codegolf lol. Nice answer Jan 21 at 15:12
• @Jacob it's quite fun to use, not having basic arithmetic forces some different ways of problem solving! Jan 21 at 20:05
• 243 by inlining V Jan 22 at 8:10
• 178? Jan 22 at 8:21
• half the golfs were me just removing stuff and seeing nothing break... chances are it's now broken somewhere Jan 22 at 8:23

# Japt, 34 bytes

*A c mA         : multiply input by 10, round up to nearest whole n, max of this and 10. Store this result in U
<0?A:U          : If U is negative, 10, else U. Store in V
"🔵"pV +"⚪"pVnA : Blue dot repeated V times, white dot repeated 10-V times
: Implicit output


Try it

## Japt-E"🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵", 24 bytes + 13 = 37

-E"s" implicitly outputs "s" if an error is thrown, but is considered a cheating flag.

*A c            : Multiply input by 10, round up to whole number. Store in U
"🔵"pU +"⚪"pUnA : Blue dot repeated U times, white dot repeated 10-V times
: Implicit: Output that, or 10 dots if (0 < input < 1) is false


Try it

# C(gcc/clang) 86 characters (126 bytes)

returns a constant string of 30 bytes, same as the original and not a null terminated string as is common in C.

const char*p(double f){return"●●●●●●●●●●○○○○○○○○○○"+3*(int)(10.5-10*(f>1?1:f<0?1:f));}

const char*p(double f){
return "●●●●●●●●●●○○○○○○○○○○" //the constant string we index into
+3*                           //each character is three bytes
(int)(                        //pointers must be integers
10.5                      //constant offset handling centering and rounding
-10*(                     //multiply up from the range 0->1 to
f>1?1:f<0?1:f         //correctly enforce the bounds
)
);
}

• Welcome to Code Golf, and nice answer! Jan 20 at 14:19
• 64 bytes Jan 20 at 16:34

# R, 48 bytes

function(i)intToUtf8(9898+118411*(0:9<10*i|i<0))


Try it online!

# Java 8, 73 bytes

p->{String s="";for(int i=0;i<=9;)s+=p<0|p>i++*.1?"🔵":"⚪";return s;}


Try it online!

Don't hesitate to correct me, or ask me if this needs explanations!

I've really tried to do this challenge using only Java Streams, but it could never beat the good ol' for :(

Here are my other attempts so far :

Classic solution using streams (85 bytes) :

p->"0123456789".chars().mapToObj(e->p<0|p*10>e-48?"🔵":"⚪").reduce("",(a,b)->a+b)


Unsuccessfully (and goofily) trying to reduce the cost of character conversion to usable int (87 bytes) :

p->"#+:?MU_mu~".chars().mapToObj(e->p<0|p*10>e/10-3?"🔵":"⚪").reduce("",(a,b)->a+b)


Dirty recursion with optional parameter to match original function call signature (113 bytes) (fails if called without parameter) :

String f(Double... p){return p.length<2?f(p[0],10d):p[1]>0?f(p[0],--p[1])+(p[0]<0|p[0]>p[1]*.1?"🔵":"⚪"):"";}


Creating a long number of exactly 10 digits composed exclusively of 9's mapped as 🔵, and 8's mapped as ⚪. This is a pure parenthesis hell, but this could potentially interest other developers to try a similar solution in other languages with less strong types and less verbose functions. (123 bytes) :

p->(""+(long)(Math.pow(10,10)-Math.pow(10,10-(int)(Math.ceil((p<0|p>1?1:p)*10)))/9)).replace("8","⚪").replace("9","🔵")

• Welcome to Code Golf, and nice answer! If the Streams answer was interesting, you should totally include it; even if it's less golfy now, someone might find a way to make it competitive, and we like creative solutions here anyway :p Jan 23 at 17:23
• Thank you @RydwolfPrograms ! I added my other solutions, for the science and/or the funniness of it :) Jan 24 at 10:53

# PowerShell Core, 59 bytes

param($a)-join(0..9|%{("⚪","🔵")[$a-lt0-or$_-lt$a*10]})


Try it online!

Fixed the behaviour for negative values, thanks Adám!

• Seems to fail on -0.1
Jan 19 at 22:30

# VyxalU, 24 bytes

01?ŀ¬∨:⌐"₀*⌈ǐẏḭ≈≠ṙ₅½*∑


Try it Online!

Utf-8 emojis amiright

## Vyxal, 16 bytes

01?ŀ[₀*⌊×*₀↲|×₀*


Try it Online!

Uses * for 🔵 and   for ⚪, otherwise I'd have to score this in utf 8.

• 24 for #1 Jan 19 at 22:48

# C# (.NET 7), 72 bytes

string a(double b,double c=0)=>c<.9?(b<0|b>c?"🔵":"⚪")+a(b,c+.1):"";


Try it here!

string a(double b,double c=0) =>  //return
c<.9                           //if counter is less than .9
?                             //then
(                         //this "X"
b<0|b>c               //if the percentage is less less than 0 or greater than the counter
?                     //then
"🔵"              //blue ball
:                     //otherwise
"⚪"              //white ball
)                         //end "X"
+                         //plus
a(b,c+.1)                 //the result of calling the same function again with the counter increased by .1
:                             //otherwise (counter is greater than or equal to 1)
"";                       //return an empty string


# Python, 55 bytes

-4 bytes thanks to l4m2 and -15 bytes thanks to Dominic van Essen.

lambda n:(10-(b:=int(10-10*n)*(0<=n<1)))*'🔵'+b*'⚪'


Attempt This Online!

• Why neec //1?
– l4m2
Jan 21 at 0:21

# APL(Dyalog Unicode), 37 bytes SBCS

Tacit function.

⎕UCS 128309 9898/⍨10(⊢,-)∘⌈10×1⌊|+0∘>


Try it on APLgolf!

0∘> is argument negative? (0 or 1)

|+ add that to the absolute value of the argument

10× multiply 10 by that

10()∘⌈ round up and then, with 10 as left argument, apply the following function:

- difference between the arguments

⊢, prepend the left argument

128309 9898/⍨ use those counts to replicate the code points

⎕UCS  convert to characters

# Pip, 33 30 bytes

Y!@a?-:-a///tt'🔵Xy.'⚪Xt-y


Attempt This Online!

### Explanation

I've replaced 🔵 and ⚪ with @ and o below so the columns will line up.

Y!@a?-:-a///tt'@Xy.'oXt-y
a                      ; Command-line argument
@                       ; Get the first character
!                        ; Negate (truthy for 0, falsey for anything else)
?                     ; If that is truthy (which means 0.0 <= a < 1.0):
-a                 ;  Negate a
//               ;  Int-divide (rounding down) by
/t             ;  1/10
;  (i.e. multiply by 10 and round down)
-:                   ;  Negate the result
; Else:
t            ;  10
Y                         ; Yank that value into y
'@Xy        ; String of y copies of @ character
'oXt-y ; String of 10-y copies of o character
.       ; Concatenate the two strings

• Funny how ! is truthy for 0 and 0.0, but falsey for -0 or -0.0. Not really valid inputs, but just something I noticed. Jan 20 at 8:35

# 05AB1E, 19 bytes

•
#*Γ•6ôç9ÝT/I@Id*è


Output as a list of characters, since strings are basically sequences of characters. But since the challenge does ask to mimic the output exactly, a trailing Join could be added for +1 byte.

Explanation:

•\n#*Γ•    # Push compressed integer 1283099898
6ô  # Split it into parts of size 6: [128309,9898]
ç # Convert both to a character with this codepoint: ["🔵","⚪"]
9Ý         # Push list [0,1,2,3,4,5,6,7,8,9]
T/       # Divide each by 10: [0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]
I@         # Check for each value in the list whether it's >= the input
I        # Push the input-decimal again
d       # Check that it's non-negative (1 if >=0; 0 if <0)
*      # Multiply that to each check, so negative inputs will become a list of 0s
è     # 0-based index each 0 or 1 into the pair of unicode characters
# (after which the list of characters is output implicitly as result)


See this 05AB1E tip of mine (section How to compress large integers?) to understand why •\n#*Γ• is 1283099898.

# C# (Visual C# Interactive Compiler), 69 bytes

void a(double b){for(int c=0;c<10;)Write(b<0|b*10>c++?"🔵":"⚪");}


Try it online!

Iterative Solution

# C# (Visual C# Interactive Compiler), 71 bytes

string a(double b,int c=0)=>c<10?(b<0|b*10>c?"🔵":"⚪")+a(b,++c):"";


Try it online!

Recursive Solution

• +1 for golfing their C# code in C# Jan 21 at 15:15

# Swift, 70 84 bytes

-2 bytes thanks to @hatcyl suggestion

var f={i in(0...9).map{i<0||i>Float($0)/10 ?"🔵":"⚪️"}.joined()}  Try it online! • Flip the >= and <= to get rid of the = and save two bytes! ( Will also have to change to an || and flip the balls around.) Jan 21 at 19:08 • @hatcyl i edited it with your suggestion, thanks! Jan 22 at 21:26 # JavaScript 6260 57 bytes ## Update. 57 bytes Slitly shorter version using [...1e9+''] to generate an array of 10 elements instead of [...Array(10)] i=>[...1e9+''].map((_,b)=>i<0|b<i*10?'🔵':'⚪').join  f=i=>[...1e9+''].map((_,b)=>i<0|b<i*10?'🔵':'⚪').join const testCases = [-2, 0, 0.01, 0.20, .666, 0.9, 0.99, 1, 10, NaN]; testCases.forEach(i => console.log(f(i), i)) .as-console { background-color: grey !important; } ## Older version Thank to @RydwolfPrograms for the join tip. Non recursive solution.  i=>[...Array(10)].map((_,b)=>i<0|b<i*10?'🔵':'⚪').join  This solution does not handle a NaN parameter. • Welcome to Code Golf, and nice answer! You can save two bytes by replacing .join('') with .join Jan 25 at 15:55 • @RydwolfPrograms what is this witchery Jan 25 at 16:09 • @RydwolfPrograms: I love that! Jan 25 at 16:09 • @Seggan You can prepend a function to a template string which acts as a preprocessor for it. E.g., String.raw. But if there's no ${...} parts, the function just gets passed ["..."] where ... is the string's contents (IIRC without escapes processed? doesn't matter here; edit: nvm). Most built-in methods will implicitly stringify that, joining it by ,, which since it's a single element array, just gives the original string. It's so cursed. Jan 25 at 17:40
• @RydwolfPrograms i knew js is worse than python Jan 25 at 18:23

# Perl, 52 54 bytes

Edit : Change condition with >=&<= to handle NaN + add note

sub k($c){join'',map$c>=0&$c<=$_/10?"⚪":"🔵",0..9}


Try it online!

#### Note

It is possible to remove the join part, because Perl default behavior when you print an array is to join it, but it feel cheaty. What you guys think ?

##### Perl Cheaty version - 47 Bytes
sub k($c){map$c>=0&$c<=$_/10?"⚪":"🔵",0..9}


Try it online!

It uses "signatures 15 years beta" feature (activable via commande line -Mfeature=signature) or via import. The old school perl take 2 bytes more :

sub j{join'',map@_[0]<0|@_[0]>$_/10?"🔵":"⚪",0..9}  #### Explaination : sub j{ join ('', # Join each element of a list with the string ''. map( # Return a list of what the block return for each element of the list passed in second argument {@_[0]<0|@_[0]>$_/10?"🔵":"⚪"} , #@_[0] is the function first parameter, $_ the current iterated element (0..9)) # Simple list }  ### Other interesting solution : ### The substr 61|59(signatures) Bytes, probably fastest and lightest solution, (OK NaN) sub b{substr'🔵'x(10).'⚪'x(10-(@_[0]<0?10:@_[0]*10)),-10} sub p($c){substr'🔵'x(10).'⚪'x(10-($c<0?10:$c*10)),-10}


### The for loop 55|57 Bytes

Work only once, dunno if it can be improve without too many bytes (KO NaN):

sub l($c){$a.=($c<0|$c>$_/10?"🔵":"⚪")for 0..9;$a}


### Recursive 81|62 Bytes

Not very interesting at first, juste a copy cat of JS. But i run into a small bug on the "old perl" version (KO NaN):

sub a{(@_[1]//=10)?a(@_[0],@_[1]-1).(@_[0]<0|@_[0]>(@_[1]-1)/10?"🔵":"⚪"):''}
sub t($n,$i=10){$i?t($n,--$i).($n<0|$n>$i/10?"🔵":"⚪"):''}


I expected this to work :

sub z{(@_[1]//=10)?z(@_[0],--@_[1]).(@_[0]<0|@_[0]>(@_[1])/10?"🔵":"⚪"):''}


But it does not. --@_1 do not work and i dont understand why.

## Excel formula, 58 82 104 bytes

-22 bytes thanks to @DominicvanEssen massive optimizations !

-24 bytes thanks to @TaylorAlexRaine even more massive optimization !

=LEFT(REPT("🔵",-INT(-10*A1^(A1>=0)))&REPT("⚪",10),10)


Put the formula in any cell, and the parameter in the "A1" cell

Alternative solution : Creating a number of exactly 10 digits composed exclusively of 9's mapped as 🔵, and 8's mapped as ⚪ (82 bytes) :

=SUBSTITUTE(SUBSTITUTE(10^10-1-INT(10^INT(10*(1-A1^(A1>=0)))/9),9,"🔵"),8,"⚪")

• 86 bytes: =REPT("🔵",10-INT(10*MAX(IF(A1<0,,1-A1),)))&REPT("⚪",INT(10*MAX(IF(A1<0,,1-A1),))) Jan 24 at 16:16
• 82 bytes: =REPT("🔵",10-INT(10*MAX(1-A1^(A1>=0),)))&REPT("⚪",INT(10*MAX(1-A1^(A1>=0),))) Jan 24 at 17:21
• 53 char, 58 bytes=LEFT(REPT("🔵",-INT(-10*A1^(A1>=0)))&REPT("⚪",10),10) Feb 24 at 3:23
• @TaylorAlexRaine Very impressive! You know some really cool Excel tricks :) Feb 24 at 8:59
• I do :D And I have written up a good bit about golfing both in Excel and VBA on their respective tips page. You might want to check them out Feb 25 at 3:59

# Jelly, 19 bytes

>⁵Ḷ÷¤»⁻A$ị“¢€:“&Ɠ’Ọ  A monadic Link that accepts a double precision floating point number and yields a list of characters. Try it online! Or see the test-suite. ### How? >⁵Ḷ÷¤»⁻A$ị“¢€:“&Ɠ’Ọ - Link: double D
⁵                  -   ten
Ḷ                 -   lowered range -> [0, 1, 2, ..., 9]
÷                -   divided by (ten) -> [0, 0,1, 0.2, ..., 0.9]
>                   - (D) greater than (that) (vectorised) -> G
$- last two links as a monad - f(D): A - absolute value (D) ⁻ - (D) not equal to (that)? -> K (K = (x<0 or x is nan)?) » - (G) maximum (K) (vectorised) -> L = list with 1 at blue and 0 at white “¢€:“&Ɠ’ - list of base 250 compressed numbers = [128309, 9898] ị - (L) index into (that) (vectorised) Ọ - cast to characters  # Retina 0.8.2, 67 bytes ^[^0]|^0.9. 10$*@
T_dd....
\d(..)?
$1$*@10$*⚪ 1M!.{10} @ 🔵  Try it online! Link includes test cases. Explanation: ^[^0]|^0.9. 10$*@


Unless the input is from 0 to 0.9 inclusive, put 10 @s at the start. (I use @ as it's a single UTF-16 character and 🔵 isn't.)

T_dd....


Increment the digits if there are at least three (not including the decimal point) i.e. leave 0, 0.1 ... 0.9.

\d(..)?.*
$1$*@10$*⚪  Convert the number of tenths (if any) into @s and also add 10 ⚪s. 1M!.{10}  Keep just the first 10 characters. This removes any surplus ⚪s and also spurious @s or ⚪ arising from later digits. @ 🔵  Turn @s into 🔵s. • Can you save any bytes by assuming that 0 will always be entered in the form 0.0? Jan 20 at 16:57 • @DLosc Well I already assume it won't be entered in the form 0.00 but technically yes, I could save a byte. – Neil Jan 20 at 17:36 # Factor, 56 bytes [| x | 10 iota [ x 10 * < x 0 < or 128309 9898 ? ] map ]  Try it online! [| x | ! a quotation taking an argument x 10 iota ! the range [0..9] [ ! start map quotation x 10 * < ! is the range number less than x times ten? x 0 < or ! or is x less than zero? 128309 9898 ? ! 128309 if so; 9898 if not ] map ! map each number in the range to something ] ! end quotation  # Arturo, 54 bytes $[x][join map 0..9'n[(or? n<x*10x<0)?->"🔵"->"⚪"]]


Try it