19
\$\begingroup\$

3D-modeling software mainly uses UV Mapping to map textures onto a 3D object. The valid values for both U and V are usually located in an inclusive [0..1] range.

Challenge

You bought a new 3D-modeling software which is super-easy to use. However there is one issue with it: it adds or subtracts a random integer number from UV values. Your task is to create a program or a function that modifies an input value to get a float value in an inclusive [0..1] range.

The resulting float should have the same fractional part as the original, and be as close to the original as possible. Because both 0 and 1 are in the output range, any integers 0 or less should change to 0, and any integers 1 or greater should change to 1.

An example algorithm in JavaScript:

function modFloat(input) {
    while (input < 0 || input > 1) {
        if (input < 0) input += 1;
        if (input > 1) input -= 1;
    }
    return input;
}

Rules

  • Input is a single integer or float value. Any reasonable format is allowed as long as it is specified in your answer.
  • The output should be a decimal representation of a float value.
  • The output precision should be at least same decimal places as input.
  • Trailing zeros are allowed.
  • Be sure your code correctly chooses which of 0 or 1 to output for integer inputs.

Test cases

Input       | Output
------------+---------
         -4 | 0
         -1 | 0
          0 | 0
          1 | 1
          2 | 1
     1.0001 | 0.000100
 678.123456 | 0.123456
-678.123456 | 0.876544
        4.5 | 0.5

This is , so the shortest code in bytes wins!

\$\endgroup\$
  • 4
    \$\begingroup\$ Do you intend for 1 to map to 1? Usually a half-open range is used. Based on your pseudocode, should I understand all integers >1 go to 1, and all integers <0 go to 0> \$\endgroup\$ – xnor Feb 24 '17 at 16:50
  • 4
    \$\begingroup\$ All %1 solutions fail if input is 1! \$\endgroup\$ – seshoumara Feb 24 '17 at 16:51
  • 9
    \$\begingroup\$ Actually, I like the 1->1 thing, it keeps the problem from being a trivial built-in for many languages. \$\endgroup\$ – xnor Feb 24 '17 at 16:52
  • 2
    \$\begingroup\$ Can I use sed for this? There are no data types in sed, the input would have to be a text stream. \$\endgroup\$ – seshoumara Feb 24 '17 at 17:16
  • 1
    \$\begingroup\$ @seshoumara any reasonable input format is allowed, so I'd say "Why not?". \$\endgroup\$ – lolbas Feb 24 '17 at 17:27

16 Answers 16

1
\$\begingroup\$

Jelly, 6 bytes

%1o>0$

Try it online!

Jelly has no True or False, but uses 1 and 0 in their place.

%1o>0$ - Main link: float v
%1     - v mod 1
     $ - last two links as a monad
   >0  -     v greater than zero?
  o    - or - replace the 0 result of the mod with 1 when v is greater than 0.
\$\endgroup\$
9
\$\begingroup\$

Python, 20 bytes

lambda x:x%1or+(x>0)

Try it online!

Takes the input modulo 1, then handles the boundary case by converting outputs of 0 to 1 for positive inputs. A bool output would save two bytes.

lambda x:x%1or x>0
\$\endgroup\$
  • \$\begingroup\$ I think 1or is breaking the syntax highlighter. (I assume it's interpreted as 1 or) \$\endgroup\$ – 12Me21 Feb 24 '17 at 17:20
  • \$\begingroup\$ @12Me21 Yes, and I haven't seen any highlighter that handles it correctly. \$\endgroup\$ – xnor Feb 24 '17 at 17:20
  • \$\begingroup\$ Mine does :) 12Me21.github.io/syntax/link#1or \$\endgroup\$ – 12Me21 Feb 24 '17 at 17:23
6
\$\begingroup\$

Brachylog, 14 11 bytes

Thanks to Fatalize for golfing 3 bytes.

∧≜:?+.≥0∧1≥

For a change, this answer doesn't use mod :)

Try it online!

Explanation

∧≜                Label an integer variable. This will start trying different
                  values for this variable, the ones closest to 0 first.
   :?+.           This variable summed to the input is equal to the output
      .≥0∧1≥      which is >= 0 and <= 1
\$\endgroup\$
  • \$\begingroup\$ This output 0 for positive integers when I tried it online. \$\endgroup\$ – Neil Feb 26 '17 at 11:24
  • 1
    \$\begingroup\$ @Neil corrected, thank you. I don't know why I missed it \$\endgroup\$ – Leo Feb 26 '17 at 13:36
  • 2
    \$\begingroup\$ You can save 3 bytes as such: ∧≜:?+.≥0∧1≥. \$\endgroup\$ – Fatalize Feb 27 '17 at 7:50
4
\$\begingroup\$

JavaScript (ES6), 19 bytes

n=>(n%1+1)%1||n>0|0

In JavaScript, n%x returns a negative number if n is negative, meaning that if we want to get the positive residue, we must add x if n is negative. (n%x+x)%x covers all cases:

n     n%1   n%1+1 (n%1+1)%1
0     0     1     0
1     0     1     0
2.4   0.4   1.4   0.4
-1    0     1     0
-2.4  -0.4  0.6   0.6

Another working solution at 20 bytes, which shows a bit more of a pattern:

n=>n%1+(n%1?n<0:n>0)
\$\endgroup\$
3
\$\begingroup\$

MATL, 9 bytes

1&\0>yg>+

Try it online! Or verify all test cases.

Explanation

Example with input 678.123456

1      % Push 1
       % STACK: 1
&\     % Implicit input. Divmod with 1
       % STACK: 0.123456, 678
0>     % Is it positive?
       % STACK: 0.123456, 1
y      % Duplicate from below
       % STACK: 0.123456, 1, 0.123456
g      % Convert to logical: nonzero becomes 1
       % STACK: 0.123456, 1, 1
>      % Greater than? This is true if fractional part of input was zero
       % and non-fractional part was positive
       % STACK: 0.123456, 0
+      % Add. Implicitly display
       % STACK: 0.123456
\$\endgroup\$
3
\$\begingroup\$

Javascript, 28 bytes

m=f=>f<0?m(f+1):f>1?m(f-1):f

Recursively decreases/increases the values by 1 until the result is in [0,1]

\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG, and nice answer! \$\endgroup\$ – ETHproductions Feb 25 '17 at 16:06
2
\$\begingroup\$

Japt, 8 bytes

u1 ªUbV1

Test it online!

I think this is the first time I've ever used b...

Explanation

 u1 ªUbV1  // Implicit: U = input, V = 0
Uu1        // Take U%1, but add 1 if U is negative. This is equivalent to %1 in Python.
    ª      // If the result is falsy (0), instead take
     UbV1  //   U bound between 0 and 1.
           // This converts positive integers to 1, zero/negative integers to 0.
           // Implicit: output result of last expression
\$\endgroup\$
2
\$\begingroup\$

Mathematica, 20 bytes

#~Mod~1/. 0/;#>0->1&

Explanation

This is a rather unusual use of /; where I'm using it more like an && because the condition after it has nothing to do with the pattern it matches.

#~Mod~1...

Compute x % 1, which is correct for all cases except positive integers.

.../. 0/;...

Replace zeros in the previous expression if...

...#>0...

...the input is positive...

...->1...

with 1.

\$\endgroup\$
2
\$\begingroup\$

PHP, 37 bytes

<?=($m=fmod($argn,1))+(!!$m^$argn>0);

Run with echo <number> | php -R '<code>'.

There are so many ways to do this ... this should be one of the shortest in PHP.

The fmod result is negative for negative floats and 0 for positive integers; those need adjustment: !!$m is true for floats, xoring with $n>0 results in false for positive float and negative int, true for negative float and positive int; + casts that to 1 or 0 - done.

\$\endgroup\$
2
\$\begingroup\$

C 57 56 73 bytes

b;f(float n){b=n;printf("%f",((!(n-b)&&n<=0)?0:n<0?1.+n-b:(n-b)?n-b:1));}

@pinkfloydx33 Thanks for pointing out!

Ungolfed version:

f(float n)
{
  int b=n;
  printf("%f",( (!(n-b)&&n<=0)?0:n<0?1.+n-b:(n-b)?n-b:1) );
}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Can you do 1. instead of 1.0? \$\endgroup\$ – Cows quack Feb 25 '17 at 8:54
  • \$\begingroup\$ @KritixiLithos I am not familiar with that notation but it seemed to work. \$\endgroup\$ – Abel Tom Feb 25 '17 at 12:03
  • \$\begingroup\$ Must you call everything f?😂 Also I don't think the parenthesis in (f<0) is necessary. \$\endgroup\$ – kennytm Feb 25 '17 at 14:59
  • \$\begingroup\$ That can be simplified I think to not replicate the subtraction. But either way it doesn't work for f(1) (which should return 1) \$\endgroup\$ – pinkfloydx33 Feb 25 '17 at 17:06
  • \$\begingroup\$ @pinkfloydx33 thanks so much for pointing it out, that code was far from done.:) Fixed it, should run fine now! \$\endgroup\$ – Abel Tom Feb 25 '17 at 18:08
1
\$\begingroup\$

SmileBASIC, 28 bytes

INPUT N?N-FLOOR(N)+(N<<0==N)
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 19 bytes

n=>(n>0==!(n%=1))+n

Explanation: %1 doesn't give the correct results in all cases:

input       %1          output
-ve int     -0
-ve frac    -ve frac    +ve frac
0           0
+ve frac    +ve frac
+ve int     0           1

An extra 1 needs to be added in the cases that are wrong, which are those of a negative non-integer and a positive integer. This is what the expression (n>0==!(n%1)) calculates.

\$\endgroup\$
  • \$\begingroup\$ There are several other arrangements of this, but I haven't yet found one that's shorter... \$\endgroup\$ – ETHproductions Feb 24 '17 at 20:39
1
\$\begingroup\$

><>, 26 bytes

:1%:?vr1(?v1n;
     >n;n0<

Try it online!

Because solutions in good golfing languages are almost always pretty instantly given, I decided to mix things up. First <>< answer!

Explanation

:1%:?vr1(?v1n;    Assume input i in stack
     >n;n0<

:                 Duplicate i (need it if i%1 != 0)
 1                Push 1
  %               Pop i and 1, push i%1
   :              Duplicate top of stack because  we need one for the if     
    ?v            If i%1 != 0 ------------------------,
      r           Reverse stack so that i is TOS      | 
       1(?v       If i > 0 (not < 1)                  |
           1n;      Print 1 and Exit                  |
                  Else                                |                   
        n0<         Print 0 and --,                   |
     >n           Print n <-------|-------------------'
       ;          Exit <----------'

Fun fact: the explanation is a valid <>< program!

\$\endgroup\$
0
\$\begingroup\$

Javascript, 41 28 bytes

n=>n-Math.floor(n)+(n<<0==n)

Math.floor() is so long...

\$\endgroup\$
  • \$\begingroup\$ n|0 is shorter than Math.floor (I think it works) \$\endgroup\$ – Cows quack Feb 24 '17 at 17:42
  • \$\begingroup\$ |0 is different than floor() for negative numbers. \$\endgroup\$ – 12Me21 Feb 24 '17 at 17:44
0
\$\begingroup\$

Pyth, 7 bytes

|%Q1s<0

Explanation

|%Q1s<0
|%Q1s<0Q      Implicitly add input
 %Q1          Input mod 1
|             Short-circuting or
    s<0Q      1 if input is positive, 0 otherwise

If you don't mind using True and False as 1 and 0, you can drop the s for 6 bytes.

\$\endgroup\$
0
\$\begingroup\$

Perl 6, 15 bytes

{+($_%1||$_>0)}

Try it online!

Inspired by seshoumara's comment that mod 1 almost works.

EDIT: Ha, xnor's Python solution beat me to it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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