Decimal Digit Truncating

7

Input:

A decimal

Output:

The input truncated

How to truncate them?

The integer part of the input will remain the same. The decimal part of the input will be truncated based on the lowest digit in consecutive order. The two step-by-step examples below should clarify what I mean by that:

Example 1: Input: 17.46940822

Step 1: Leave the integer part unchanged: 17
Step 2: Look at the first decimal digit, and truncate it to that many decimal digits: 4.4694
Step 3: Look at the next decimal digit. If it's lower, adjust the truncation accordingly. If not, continue to the next decimal digit: 6 → remains .4694
Step 3 again: 9 → remains .4694
Step 3 again: 4 → remains .4694

So the output will be: 17.4694.

Example 2: Input: 10.4521084

Step 1: Leave the integer part unchanged: 10
Step 2: Look at the first decimal digit, and truncate it to that many decimal digits: 4.4521
Step 3: Look at the next decimal digit. If it's lower, adjust the truncation accordingly. If not, continue to the next decimal digit: 5 → remains .4521
Step 3 again: 2 → truncation adjusted to: .45

So the output will be: 10.45

Challenge rules:

  • You are allowed to take the input as decimal, string, list/array/stream of characters, etc. (Same applies to the output, although I doubt there are a lot of languages that have the proper truncation while remain working with decimal values.)
    You are also allowed to use a comma , instead of a dot . (perhaps useful for regex-based solution/languages).
  • If the decimal part is not long enough for the truncation, you are optionally allowed to add trailing zeros. I.e. 123.4 can be both 123.4 or 123.4000
  • If you have to truncate to 0 decimal digits we omit the decimal digits. The dot/comma may remain optionally if you use strings. I.e. 847.3072847 (or 847.)
  • You can assume the input will always contain at least one decimal digit, so 123 won't be an input, but 123.0 can be an input.

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code (i.e. TIO).
  • Also, adding an explanation for your answer is highly recommended.

Test cases:

Input:          Output:

17.46940822     17.4694
10.4521084      10.45
123.4           123.4000 (or 123.4)
-847.3072       -847 (or -847.)
123.0           123 (or 123.)
98.76543210     98.7654
0.3165          0.3
-0.1365         -0.1
82937.82937     82937.82
-0.1010101      -0.1
-1.0101010      -1 (or -1.)
28.684297       28.68
13.35           13.350 (or 13.35)
0.99999999999   0.999999999
28.321          28.32
0.56462         0.5646

Kevin Cruijssen

Posted 2018-10-30T09:00:43.720

Reputation: 67 575

Need we output string? – l4m2 – 2018-10-30T09:05:05.893

@l4m2 No, you are also allowed to output it as a decimal, or list of characters. Although I don't know a lot of languages that can do the proper truncation without converting to string format. – Kevin Cruijssen – 2018-10-30T09:06:10.727

So it's fine to remove ending zero if outputing float? – l4m2 – 2018-10-30T09:07:32.877

@l4m2 Sure. I've updated the rules to also allow no additional trailing zeros. – Kevin Cruijssen – 2018-10-30T09:09:15.880

Suggest test case 0.99999999999 -> 0.999999999 – None – 2018-10-30T11:32:58.020

1

Suggested test case 0.56462 (This Jelly code passes all other given test cases :()

– Jonathan Allan – 2018-10-30T21:40:17.837

@JonathanAllan Done. – Kevin Cruijssen – 2018-10-30T21:57:25.020

Answers

4

05AB1E, 18 bytes

2 bytes extra due to a bug with £ not handling 0 correctly.

'.¡`DvÐgsNè-F¨]'.ý

Try it online! or as a Test Suite

Explanation

    '.¡                 # split input on "."
       `                # push int and decimals separately to stack
        D               # duplicate decimal digits
         v              # for each
          Ð             # triplicate the current decimal digits
           g            # get the length
            sNè         # get the Nth digit
               -        # subtract from the total length
                F¨]     # drop that many digits from the end
                        # end loop
                   '.ý  # join on "."

Emigna

Posted 2018-10-30T09:00:43.720

Reputation: 50 798

4

Python 2, 103 101 98 94 93 87 bytes

a,b=input().split('.');i,w=0,len(b)
while w>i:w=min(int(b[i]),w);i+=1
print a+'.'+b[:w]

Try it online!


Saved:

  • -2 bytes, thanks to Kevin Cruijssen
  • -3 bytes, thanks to Vedant Kandoi
  • -4 bytes, thanks to Lynn

TFeld

Posted 2018-10-30T09:00:43.720

Reputation: 19 246

a+w+1 can be a-~w. Nice answer though, +1 from me. – Kevin Cruijssen – 2018-10-30T09:21:08.277

2Oh, and return can be print as well. And here you are golfing Python for years. Tsk tsk tsk. ;p (It's the simplest things we usually forgot to golf I guess.) – Kevin Cruijssen – 2018-10-30T09:32:42.497

Instead of a function, use n=input() and remove the spaces and print as mentioned by @KevinCruijssen to save a few bytes. – Vedant Kandoi – 2018-10-30T10:06:15.420

I think while w>=i<a+i<len(n): is okay, as the . is never at the start of the string, so a>0. – Lynn – 2018-10-30T11:43:08.850

1@KevinCruijssen Thanks :) Ye have little faith :( . I didn't really have time to golf it, I just submitted a working solution, and left for a couple of hours. – TFeld – 2018-10-30T12:53:31.627

3

JavaScript (Node.js), 58 bytes

f=(s,p=1/0,q=1,c=s[q])=>c?f(s.slice(0,p-~c),++c?p:q,q+1):s

Try it online!

tsh

Posted 2018-10-30T09:00:43.720

Reputation: 13 072

Ridiculously & unnecessarily complicated and for the same score as my boring, straightforward solution?! +1 – Shaggy – 2018-11-02T23:08:10.620

@Shaggy Actually, they are similar enough. s.slice(0,p-~c) -> d.slice(0,-~d[n]), q+1 -> ++n, both recursive. Only difference is how to handle digits before the dot. – tsh – 2018-11-03T07:22:30.767

2

Charcoal, 28 bytes

≔⪪S.θW⊟EθΦκ‹ΣμLκ⊞θ…⊟θI§ι⁰⪫θ.

Try it online! Link is to verbose version of code. Explanation:

≔⪪S.θ

Split the input on ..

W⊟EθΦκ‹ΣμLκ

Filter each part on those digits that are less than the string's length. Then take the last result. (This saves 1 byte over filtering on just the decimals.) Loop until that is empty.

⊞θ…⊟θI§ι⁰

Take the first filtered digit and truncate the decimals to that length.

⪫θ.

Join the parts back together and implicitly print.

Neil

Posted 2018-10-30T09:00:43.720

Reputation: 95 035

Seems to give an incorrect result for the negative input-cases (although it is possible I don't know how to input negative values in Charcoal, I tried with a leading - or _, but both failed). Everything else works fine. – Kevin Cruijssen – 2018-10-30T10:45:55.347

1@KevinCruijssen Ah, my final golf broke because it tried to cast - to integer. Fortunately I can use Sum instead. – Neil – 2018-10-30T12:15:16.660

2

C (gcc), 84, 78 bytes

Takes input as a pointer to a string buffer, outputs by modification. Note that providing a pointer to a buffer that is too small (intPartLen + 1 + 9 > bufSize) can cause SEGFAULT.

If assuming the size of the buffer to be sufficient is not allowed, +7 to the score.

l,M;f(char*F){F=strchr(F,46);for(l=47,M=57;*++F&&++l<M;*F<M?M=*F:0);F[M-l]=0;}

Try it online!

Degolf

l,M;f(char*F){
    F=strchr(F,46); // Find the pointer to the period.
    for(l=47,M=57;  // Initialize variables (48='0', 57='9')
            *++F&&++l<M;  // Check for null terminator, and that we're not
                          // going through too many decimals
            *F<M?M=*F:0); // Keep smaller of M and the char pointed to by F.
        F[M-l]=0; // Explained below.
}

At the end of the loop, F is a pointer to the nth decimal after the decimal point (ptr). M is the smallest digit observed as its ASCII value. l is '0'+n-1 (or 47+n). Thus:

F[M-l] == *(F + M - l)
F[M-l] == *(ptr + n + M - '0' - n + 1)
F[M-l] == *(ptr + M - '0' + 1)

Which gives us a pointer to the first character to truncate; replacing this character with a \0 results in the truncation of the remaining digits for most intents and purposes. This is also where the SEGFAULT happens; for example, if the input is 123.4, the smallest digit is 4, and the pointer will point to the character * in 123.4\0??*.

user77406

Posted 2018-10-30T09:00:43.720

Reputation:

2

Ruby -pl, 48 bytes

c=i=j=$_=~/,/;$_=$_[0,c.to_i-~j]while c=$_[i+=1]

Try it online!

Uses a decimal comma instead of a dot.

Kirill L.

Posted 2018-10-30T09:00:43.720

Reputation: 6 693

2

PHP, 92 bytes

several solutions, same length:

# any PHP:
for($n=$argn,$t=9;~$d=$n[$i+++$p=1+strpos($n,46)];$n=substr($n,0,$p+$t))$t<$d||$t=$d;echo$n;
for($t=9;$i<$t&&~$d=$n[$i+++$p=1+strpos($n=$argn,46)];)$t<$d||$t=$d;echo substr($n,0,$p+$t);
for($t=9;$i<$t&&~$d=$n[++$i+$p=strpos($n=$argn,46)];)$t<$d||$t=$d;echo substr($n,0,$p+$t+1);

# PHP 7:
for($t=9;~$d=($n=&$argn)[$i+++$p=1+strpos($n,46)];$n=substr($n,0,$p+$t))$t<$d||$t=$d;echo$n;
for($n=$argn;~$d=$n[$i+++$p=1+strpos($n,46)];$n=substr($n,0,$p+$t))($t??9)<$d||$t=$d;echo$n;

Run as pipe with -nR or try (most of) them online.

Titus

Posted 2018-10-30T09:00:43.720

Reputation: 13 814

I was like, wow, that's a long PHP answer. But then I saw the byte-count and realized they are four separated programs. ;) Btw, in what order does PHP execute $i+++$p=1+strpos($n,46)? – Kevin Cruijssen – 2018-10-30T13:59:34.470

@KevinCruijssen $i++, then $p=.... ++$p=... would throw a parse error. – Titus – 2018-10-30T14:05:42.813

2

JavaScript, 58 bytes

Input and output as a string, using a comma as the decimal separator.

s=>s.replace(/,.+/,g=d=>d[++n]?g(d.slice(0,-~d[n])):d,n=0)

Try it online

Shaggy

Posted 2018-10-30T09:00:43.720

Reputation: 24 623

1

JavaScript (Node.js), 78 68 bytes

-10 bytes from @tsh

a=>eval('for([x,y]=a.split`.`,i=0;c=y[i++];y=y.slice(0,c));x+`.`+y')

Try it online!

Luis felipe De jesus Munoz

Posted 2018-10-30T09:00:43.720

Reputation: 9 639

A quick saving using comma as the decimal separator. – Shaggy – 2018-10-30T21:22:32.540

68 bytes – tsh – 2018-10-31T09:02:54.753

1

Perl 6 -p, 57 41 bytes

$!=m/\./.to;.=substr(0,$!+$/)while m:c/./

Try it online!

Explanation

$!=m/\./.to;       # Store position of decimal point in $!
.=substr(0,$!+$/)  # Truncate string to length $!+$/
while m:c/./       # while there's a match for the next digit

nwellnhof

Posted 2018-10-30T09:00:43.720

Reputation: 10 037

1

Python 3, 77 bytes

g,h=input().split(".")
for i in h:h=h[:int(i)]if i in h else h
print(g+"."+h)

Try it online!

Somehow, despite slicing past the end of a string and modifying while iterating on that same string, the interpreter doesn't complain.

This answer has a similar structure to the other Python one, but uses a different method to find where to truncate and works in newer versions of Python.

ivzem

Posted 2018-10-30T09:00:43.720

Reputation: 1 129

1

Clean, 115 bytes

import StdEnv,Text
$s#[i,d:_]=split['.']s
=i++['.':iter 9(\p=hd([take n\\n<-map digitToInt p|n<length p]++[id])p)d]

Try it online!

Defines the function $ :: [Char] -> [Char]. Link includes test suite.

Οurous

Posted 2018-10-30T09:00:43.720

Reputation: 7 916