Shortest Minmod Function

24

3

The minmod function is a variant of the familiar min, which appears in slope-limiting high-resolution schemes for partial differential equations. Given a number of slopes, it picks out the flattest slope, while taking care of relative signs between the slopes.

The function takes an arbitrary number of parameters. Then minmod(x1, x2, ..., xn) is defined as:

  • min(x1, x2, ..., xn), if all xi are strictly positive
  • max(x1, x2, ..., xn), if all xi are strictly negative
  • 0, otherwise.

We'll only consider integer inputs, because that does not really affect the implementation and should be more inclusive for some (esoteric) languages.

Write a program or function, which takes n signed integers (for n > 0) via STDIN, ARGV or function argument (you can use an array if that's more convenient than a variadic function), and returns or prints (to STDOUT) the result of minmod(a,b).

You must not use built-in min or max functions (and obviously, no built-in minmod either, if you can actually find that). In addition, you must not use any built-in sorting functions, except to sort a fixed small number of items (less than 5).

If your language doesn't have signed types, you may use an unsigned type and interpret it as two's complement. E.g. if your language only uses unsigned bytes, you can use 255 to stand in for -1 and 128 to stand in for -128, etc.

This is code golf, so the shortest answer (in bytes) wins.

Test Cases

Input          Output

2              2
-3             -3
0              0
3 -5           0
2 4 1          1
0 1 2          0
-1 1 2         0
-4 -2 -3 -2    -2
-5 0 -1        0
1 0 -1         0

Leaderboards

The following Stack Snippet generates both a regular leaderboard and an overview of winners by language. So even if your language of choice doesn't let you win the entire challenge, why not try to snatch a spot on the second list?

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){$.ajax({url:answersUrl(page++),method:"get",dataType:"jsonp",crossDomain:true,success:function(e){answers.push.apply(answers,e.items);if(e.has_more)getAnswers();else process()}})}function shouldHaveHeading(e){var t=false;var n=e.body_markdown.split("\n");try{t|=/^#/.test(e.body_markdown);t|=["-","="].indexOf(n[1][0])>-1;t&=LANGUAGE_REG.test(e.body_markdown)}catch(r){}return t}function shouldHaveScore(e){var t=false;try{t|=SIZE_REG.test(e.body_markdown.split("\n")[0])}catch(n){}return t}function getAuthorName(e){return e.owner.display_name}function process(){answers=answers.filter(shouldHaveScore).filter(shouldHaveHeading);answers.sort(function(e,t){var n=+(e.body_markdown.split("\n")[0].match(SIZE_REG)||[Infinity])[0],r=+(t.body_markdown.split("\n")[0].match(SIZE_REG)||[Infinity])[0];return n-r});var e={};var t=1;answers.forEach(function(n){var r=n.body_markdown.split("\n")[0];var i=$("#answer-template").html();var s=r.match(NUMBER_REG)[0];var o=(r.match(SIZE_REG)||[0])[0];var u=r.match(LANGUAGE_REG)[1];var a=getAuthorName(n);i=i.replace("{{PLACE}}",t++ +".").replace("{{NAME}}",a).replace("{{LANGUAGE}}",u).replace("{{SIZE}}",o).replace("{{LINK}}",n.share_link);i=$(i);$("#answers").append(i);e[u]=e[u]||{lang:u,user:a,size:o,link:n.share_link}});var n=[];for(var r in e)if(e.hasOwnProperty(r))n.push(e[r]);n.sort(function(e,t){if(e.lang>t.lang)return 1;if(e.lang<t.lang)return-1;return 0});for(var i=0;i<n.length;++i){var s=$("#language-template").html();var r=n[i];s=s.replace("{{LANGUAGE}}",r.lang).replace("{{NAME}}",r.user).replace("{{SIZE}}",r.size).replace("{{LINK}}",r.link);s=$(s);$("#languages").append(s)}}var QUESTION_ID=42079;var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";var answers=[],page=1;getAnswers();var SIZE_REG=/\d+(?=[^\d&]*(?:&lt;(?:s&gt;[^&]*&lt;\/s&gt;|[^&]+&gt;)[^\d&]*)*$)/;var NUMBER_REG=/\d+/;var LANGUAGE_REG=/^#*\s*([^,]+)/
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><link rel=stylesheet type=text/css href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id=answer-list><h2>Leaderboard</h2><table class=answer-list><thead><tr><td></td><td>Author<td>Language<td>Size<tbody id=answers></table></div><div id=language-list><h2>Winners by Language</h2><table class=language-list><thead><tr><td>Language<td>User<td>Score<tbody id=languages></table></div><table style=display:none><tbody id=answer-template><tr><td>{{PLACE}}</td><td>{{NAME}}<td>{{LANGUAGE}}<td>{{SIZE}}<td><a href={{LINK}}>Link</a></table><table style=display:none><tbody id=language-template><tr><td>{{LANGUAGE}}<td>{{NAME}}<td>{{SIZE}}<td><a href={{LINK}}>Link</a></table>

Martin Ender

Posted 2014-12-01T15:30:31.490

Reputation: 184 808

Reading the input will not be in O(n) if there isn't a limit. – jimmy23013 – 2014-12-01T15:42:14.873

@user23013 Good point. I removed this altogether, because I only added it to rule out sorting functions in the first place. So instead I'm now simply doing exactly that. – Martin Ender – 2014-12-01T15:45:27.643

1Maybe add a column for how many answers are there in each language – proud haskeller – 2014-12-01T21:45:49.557

1@proudhaskeller Hmm, I like that the two tables currently fit next to each other without having go open the snippet full screen - I think it would be a bit too crammed if I added another column. If your comment gets significantly more upvotes than mine, I'll see what I can do. ;) – Martin Ender – 2014-12-01T21:48:04.387

Both +1'ed.. ;) – Timtech – 2014-12-01T22:54:44.063

I've now allowed sorting of small fixed arrays (as per popular demand). – Martin Ender – 2014-12-01T23:19:51.553

as per the chat* – Timtech – 2014-12-02T01:20:24.843

@MartinBüttner I think the allowing sorting at this stage is destructive and changes the whole thinking angle towards the question, rendering all existing (answers added before this rule addition) kind of useless and obsolete. – Optimizer – 2014-12-02T06:28:14.800

@Timtech and a couple of answers. – Martin Ender – 2014-12-02T10:07:32.680

1@Optimizer I decided that the previous version of the rules was doing more harm to the creativity of people's answers than I had intended. In addition, I was going to award a bounty to the answer that was leading before the rule change anyway so I don't think any harm in terms of rep is done either. (Yes, I agree that rule changes aren't such a good idea, but I figured it would be worth it in this case.) – Martin Ender – 2014-12-02T10:09:15.880

1@MartinBüttner - I don't see any creativity in the newer answers now. It has all come down to reducing to a pairwise minmod. Creativity was in xnor's answers or Mig's approach on which many other answers are influenced on. – Optimizer – 2014-12-02T11:12:18.863

True, xnor's solution was brilliant, and I think the newer answers are a bit cheaty. – Timtech – 2014-12-02T12:19:38.820

2@Optimizer, it's not always possible to tell whether a new answer is exactly as creative as an older one which it's similar to or whether it's an unimaginative port. – Peter Taylor – 2014-12-02T12:39:23.657

Answers

13

GolfScript, 10 9 bytes

~{0]$1=}*

Assumes input from stdin in the format [-4 -2 -3 -2]

This uses the built-in sort function $, but every time it's invoked it's on an array of 3 elements, which is permitted.

Online demo

Peter Taylor

Posted 2014-12-01T15:30:31.490

Reputation: 41 901

Cool, our answers are less than 1 second apart, which means my answer used to be the shortest. ;) – Timtech – 2014-12-02T00:02:55.173

1+1, this is way shorter and smarter than my solution. (Ps. In case anyone doubts it, yes, this solution is correct, and it's fairly easy to prove by induction. What Peter's code does is repeatedly compute the median of the previous minmod value, the next input value and zero; an examination of the possible cases shows that this indeed yields the new minmod value.) – Ilmari Karonen – 2014-12-02T00:03:39.327

What the...well, there is always LOTS of stuff to lean :O – TheBlastOne – 2014-12-06T23:42:26.253

24

Mathematica, 19 bytes

Median[#~Riffle~0]&

Code and golfing thanks to Martin Büttner.

This is an unnamed pure function that takes in a list of integers as input. Invoke it like

Median[#~Riffle~0]&[{-2, -3, -2, -4}]

or similarly saved to variable.

The code first riffles a zero in between every two elements of the input list, which inserts n-1 zeroes among n elements. Then, it takes the median to produce the answer.

This gives min-mod because it handles each case:

  1. All the numbers are positive, in which case the zeroes are below them and the median is the lowest positive number.

  2. All the numbers are negative, in which case the zeroes are above them and the median is the least negative number.

  3. There's both a positive and negative number, and so the middle element is a zero.

If Mathematica implements its median using the linear-time selection algorithm, then this is also O(n).

xnor

Posted 2014-12-01T15:30:31.490

Reputation: 115 687

11

Haskell, 62 61 39 38 37 bytes

f s=last[x|x<-0:s,and[x*x<=x*y|y<-s]]

using some comparison magic borrowed from @Zgarb's answer* , namely, x*x<=x*y.

x*x<=x*y is true only when x and y have the same sign and y's absolute value is bigger. note that when x is 0 it is always true.

we determine that x is the result iff it is contained in s, and that for all y in s x has the same sign as y and is smaller in absolute value. if no value in s satisfies this definition, then 0 is the result.

f then works by searching s for an element to satisfy this, and uses 0 as a default.

*though he didn't use it for the reasons I'm using it, and he actually got rid of it by now

proud haskeller

Posted 2014-12-01T15:30:31.490

Reputation: 5 866

Rare for Haskell to be this golfable (and, ironically, still readable). Love it. – Isiah Meadows – 2014-12-03T22:08:52.593

10

JavaScript (ES6), 39 bytes

a=>a.reduce((p,c)=>p*c>0?p*p>c*c?c:p:0)

Michael M.

Posted 2014-12-01T15:30:31.490

Reputation: 12 173

1Love this. Nice use of ES6. – Qix - MONICA WAS MISTREATED – 2014-12-03T03:41:58.773

6

Python 2, 53

lambda l:reduce(lambda a,b:sorted([a,b,0])[1],l,l[0])

The idea is to use reduce to turn the two-input min-mod finder into an n-input one. I came up with it independently of the other answers that use it. Only Python 2 supports reduce.

The two-input solution simply finds the median of the two numbers and zero. See my Mathematica answer for a more direct way to use the median.

Less golfed:

def f(l):
 A=l[0]
 for x in l:A=sorted([a,b,0])[1]
 return A

A hypothetical amalgam of Python 2 and Python 3 would be a character shorter, with the starred assignment from Python 3 and input() and print from Python 2.

#Not real code!
A,*l=input()
for x in l:A=sorted([A,x,0])[1]
print A

Old code, without sorting:

lambda l:reduce(lambda a,b:[a,b][a*a>b*b]*(a*b>0),l,l[0])

xnor

Posted 2014-12-01T15:30:31.490

Reputation: 115 687

Hm, yes, I noticed that side-effect in the meantime, but I feel like it's too late to fix it now. Mathematica has a built-in Median though. – Martin Ender – 2014-12-01T20:54:31.007

Your latter approach is now valid, too. – Martin Ender – 2014-12-01T23:20:21.230

6

Marbelous, 210 bytes

@0
00
]]\\&002
/\..//&0@0
00..02
MMMMMM//\\
:M
}0}1}0}1}0}1}0}2..}2
^7^7||||&0&1&4<3&0=2{>
EqalLteq{0{<{<<2&1--
&2..&3..}100..&2\/{>
>0&6=0&4&5&6..\/
&3..&5\/{<{0
\/..\/
:|
}000}0
&0Subt
{0&1
}0{0
^7
=0&1
&0
\/

There are three boards used here.

The | board (Ab in the readable version) takes the absolute value of a marble (by either returning the passed marble or zero minus the passed marble, as all arithmetic in Marbelous is unsigned).

The M board (Minabs in the readable version) finds and outputs to the left either the first or second marble passed (whichever has a smaller absolute value), and exiting if a different signed marble is passed.

The M board also releases the marble it holds downward instead of leftward once the last character from STDIN is fetched.

The M board is used in the main board to store the minmod of all checked values at any given time, as it releases the value to be saved leftward, which is then deflected back in.

Trashbins (\/) were only placed under synchronisers that would otherwise print to STDIN.

Input/Output uses STDIN/STDOUT. Both deal with 8-bit values (if you wanted to pass +0x30 and +0x38, place 08 into STDIN).

Libraries and cylindrical boards are both required. Viewing output as decimal numbers is recommended (note that this displays the unsigned value of the minmod result).

Test it here.

Note: For more human-friendly input/output, add Dp under the last line of the main board (before :M), replace ]] with Rd, and add the following at the bottom:

:Rd
}0}0}0
]]]]]]{>
-O-O-O
-O-O-O
*A
Plus
\\*A
..Plus
..{0
:*A
}0}0
<<<<
<<
<<
Plus
{0

This simply changes the output to be 3 decimal digits. Likewise, input with these changes requires a space separated list of 3 decimal digits per number.

Readable Version:

Board Picture

es1024

Posted 2014-12-01T15:30:31.490

Reputation: 8 953

5

Haskell, 83 40 39 bytes

This is probably not the shortest possible Haskell solution (and certainly won't beat the others here), but it's a start. EDIT: Now over 50 % shorter! EDIT2: One byte less...

a#b|a*b<0=0|a*a<b*b=a|1<2=b
m=foldr1(#)

This is just a straightforward fold (or reduce, as some languages call it) by the binary operator #, which computes the median of a, b and 0. Even though the rules would now allow me to sort small lists, this requires an import in Haskell and results in a higher byte count (49 bytes, but 31 without the import):

import Data.List
a#b=sort[a,b,0]!!1
m=foldr1(#)

Zgarb

Posted 2014-12-01T15:30:31.490

Reputation: 39 083

\a-> (signum a,a) is the same as signum>>=(,) using the function monad instance. (see my post in "tips for golfing in haskell") – proud haskeller – 2014-12-01T17:07:52.730

Thanks for the tip, but it's now moot. :) – Zgarb – 2014-12-01T18:11:08.200

@Zgarb Ah okay. – Optimizer – 2014-12-02T12:47:58.540

5

TIS-100, 696 526 bytes

@1
MOV UP ACC
SAV
ADD 999
JEZ A
SWP
MOV 1 ANY
MOV ACC ANY
JRO -7
A:MOV 12 ANY
@5
S:JRO UP
MOV UP ACC
JLZ A
JEZ B
MOV 1 DOWN
JMP B
A:MOV 7 DOWN
NEG
B:MOV 1 RIGHT
MOV ACC RIGHT
MOV ACC RIGHT
JMP S
MOV 14 DOWN
MOV 9 RIGHT
@6
MOV 999 ACC
L:JRO LEFT
SAV
SUB ANY
JGZ A
MOV ANY NIL
SWP
JMP L
A:MOV ANY ACC
JMP L
MOV ACC ANY
@9
S:JRO UP
JEZ A
SUB 1
JEZ A
JMP X
A:MOV 1 ACC
JMP S
JEZ B
SUB 2
JEZ B
X:MOV 6 ACC
JMP S
B:MOV 2 ACC
JMP S
MOV ACC ANY
@10
MOV LEFT ACC
ADD 1
JRO ACC
JRO 6
MOV UP ANY
MOV UP ACC
NEG
MOV ACC ANY
!NOP
MOV 0 ANY

Expects the sequence to be terminated by -999. TIS-100 is newer than this question, but it's not like that matters here anyway.

Node 9 keeps track of whether we're all positive, all negative or mixed. Nodes 5 and 6 work to find the minimum of the absolute value of all input numbers. Node 10 then selects the minimum, the minimum negated, or 0 depending on node 9's state.

enter image description here

Sp3000

Posted 2014-12-01T15:30:31.490

Reputation: 58 729

I have implemented a TIS emulator for TIO, so you can now try it online!

– Phlarx – 2018-05-02T20:00:56.970

4

CJam, 20 bytes (or 10 bytes)

q~{]__~z\z<=\~*0>*}*

Using @xnor's approach, reduce calculating minmod of 2 numbers at a time from the array.

This would have been 19 bytes if :z worked


Using the new rule of using sorts on short arrays:

q~{0]$1=}*

which is exactly equivalent to @Peter's answer


Previous 26 bytes asnwer:

q~_{g}%_|:+\(z\{za+_~>=}/*

This can be golfed further...

Input (via STDIN) is the integer array like :

[-4 -2 -3 -2]

and output is the minmod of the input array

Try it here

If only :g and :z worked, this would have been 4 bytes shorter.

Optimizer

Posted 2014-12-01T15:30:31.490

Reputation: 25 836

25 bytes: q~_{g}%_|:+\{z\za+_~>=}**. – jimmy23013 – 2014-12-01T17:34:29.140

Fails for single int array. I tried it too :) – Optimizer – 2014-12-01T17:36:37.967

Although there is a 26 byte solution in there . Thanks for that :) – Optimizer – 2014-12-01T17:38:49.713

4

TI-BASIC, 19 bytes

Assumes input in the format {-2,4,3}.

Works similarly to xnor's answer:

Input L₁              get user input into the L1 array
dim(L₁)2-1→dim(L₁     get the length of the array; multiply by 2 and subtract 1
                      make this the new length (new elements always default to 0)
median(L₁             calculate and return (since it's the last line) median of new array

Timtech

Posted 2014-12-01T15:30:31.490

Reputation: 12 038

My code, as well as median(augment(Ans,0ΔList(Ans at only eight bytes, fails on lists of dimension one. If variance(Ans:augment(Ans,0ΔList(Ans:median(Ans is longer than yours. If only TI-BASIC supported empty lists... – lirtosiast – 2015-05-20T18:18:50.407

You are right. It looks like that bumps my code size from 12 to 15 bytes. – Timtech – 2015-07-08T20:00:02.867

I guess you're right. +4 bytes there. – Timtech – 2015-07-09T20:44:14.360

3Interesting way of counting code size... – Ypnypn – 2014-12-02T02:22:58.133

3

@Ypnypn turns out, we're fine with it, though

– Martin Ender – 2014-12-02T10:20:48.960

4

Java, 84 bytes

This is Java in all its glory. Beats GolfScript by a factor of slightly over 900%.

int f(int[]a){int b=a[0],c;for(int d:a)b=(c=d<0?-1:1)*b<0?0:d*c<b*c?d:b;return b;}

Wrapped in class:

public class MinModGolfed{

    public static void main(String[] args){
        int[] numbers = new int[args.length];
        for (int i = 0; i < args.length; i++){
            numbers[i] = Integer.parseInt(args[i]);
        }
        System.out.println(new MinModGolfed().f(numbers));
    }

    int f(int[]a){int b=a[0],c;for(int d:a)b=(c=d<0?-1:1)*b<0?0:d*c<b*c?d:b;return b;}

}

Expanded with comments:

public class MinModExpandedGolfed{

    public static void main(String[] args){
        int[] numbers = new int[args.length];
        for (int i = 0; i < args.length; i++){
            numbers[i] = Integer.parseInt(args[i]);
        }
        System.out.println(new MinModExpandedGolfed().f(numbers));
    }

    int f(int[]a){                  //a is the input numbers
        int b=a[0],c;             //b is the best number found so far.
        for(int d:a)               //Iterate over a with current element as d.
            b=(c=d<0?-1:1)         //c is equal to the sign of d.
                    *b<0?
                        0:          //If b has opposite sign of d, b = 0.
                        d*c<b*c?d:b;//If the absolute value of d is less than b, b = d. 
        return b;
    }

}

Note: This can be improved using Java 8.

Note: Effort to improve in Java 8 failed.

TheNumberOne

Posted 2014-12-01T15:30:31.490

Reputation: 10 855

I have much to learn yet. +1. – Rodolfo Dias – 2014-12-03T08:35:01.633

4

J, 20 12 bytes

Function taking the list as argument. Stolen from the Golfscript/CJam/whatever.

(1{0/:~@,,)/

The minmod of x and y is the median (sort /:~ and take the middle 1{) of the three item list 0,x,y. Reduce the list (folding in J parlance) by taking this minmod between adjacent elements.

In use at the REPL. (J spells its negative sign _.)

   (1{0/:~@,,)/ _4 _2 _3 _2
_2
   f =: (1{0/:~@,,)/    NB. give it a name
   f 1 1 2
1
   f 0 1 2
0
   f _1 1 2
0

Old garbage, before I noticed short sorts are allowed: 0:`<.`>.@.(*@]*0<*))/ The minmod of x and y is 0 (0:) if 0 is greater than or equal to the product of x and y, else it is the min (<.) or the max (>.) between x and y depending on the sign. Fold this over the whole list.

algorithmshark

Posted 2014-12-01T15:30:31.490

Reputation: 8 144

3

Python 2, 82 79 71 69 61 bytes

lambda l:reduce(lambda G,H:[H,G][(G>H)^(G>0)]*(G*H>0),l,l[0])

This is based off of my pyth answer, which was inspired by Mig's answer.


Old answer:

l=input()
m=l[0]
k=1-2*(m<0)
for i in l:m=[m,i][m>i*k]
print(k*m>0)*m

This is a very long answer. I feel like having 2 variables is a waste...? I was right...? ish? ;p

FryAmTheEggman

Posted 2014-12-01T15:30:31.490

Reputation: 16 206

3

Pyth, 25 22 20 12

uhtS[0GH)QhQ

Probably not novel, but original :P


Pre-sorting allowed

u*?Gx>GH>G0H>*GHZQhQ

Pyth

Try it online.

The idea to use reduce and ternary statements was shamelessly stolen from Mig's answer, but I have no idea if these algorithms are otherwise even similar, as I can't read ternary statements.

Explanation:

Q=eval(input)         : implicit
u                QhQ  : print reduce(lambda G,H: ..., Q, Q[0])
 *          >*GHZ     : ... * (G*H>0)
  ?G       H          : G if ... else H
    x>GH>G0           : G>H xor G>0

FryAmTheEggman

Posted 2014-12-01T15:30:31.490

Reputation: 16 206

No need of tQ. Q will also work – Optimizer – 2014-12-01T17:55:56.017

Quite right! I also think I can remove one of the ? for a *... – FryAmTheEggman – 2014-12-01T17:56:41.540

3

KDB/Q, 43 characters for function body definition

Thanks to great ideas from previous posts:

f:{$[all 1_0<(*':)x;{$[<[x*x;y*y];x;y]}/[x];0]}

Enter single number using enlist

f[enlist 2]
f[enlist 0]
f[enlist -2]
f[2 4 1]
f[0 1 2]
f[1 0 2]
f[-1 1 2]
f[-4 -2 -3 -2]
f[-5 0 -1]
f[-5 -0 -1]
f[1 0 -1]

I'm sure some Q guru can come up with shorter ones.

space889

Posted 2014-12-01T15:30:31.490

Reputation: 31

Perhaps something like {asc[0,x,y]1}/? – algorithmshark – 2014-12-03T09:41:05.490

3

C#, 101 bytes

My first try at code golfing and in a pretty golfing hostile language. Based on reduce (Aggregate in LINQ) and very similar to the JavaScript answer by Mig. Can be run like (new System.Linq.M()).m(new[] {1, 2, 3}). Passes all test cases, but doesn't handle empty input arrays.

namespace System.Linq{class M{public int m(int[]i){return i.Aggregate((a,b)=>a*b>0?a*a<b*b?a:b:0);}}}

Jacob Bundgaard

Posted 2014-12-01T15:30:31.490

Reputation: 131

1There's no need to handle empty input, as I didn't even define the function for that case. – Martin Ender – 2014-12-02T17:46:52.293

3

J, 12 bytes

   (=&**>&|{,)/

The function reduces the list (called folding (/) in J) with the expression:

(signum(x) == signum(y)) * [x,y][abs(x)>abs(y)] where

[x,y][abs(x)>abs(y)] is y if abs(x) > abs(y) else x.

Example:

   (=&**>&|{,)/ 5 2 6
2

Try it online here.

randomra

Posted 2014-12-01T15:30:31.490

Reputation: 19 909

2

Java, 353 304 124 bytes

Put together the worst language for code golf with the world's worst golfer and you get...

int m(int[]a){int m=a[0];if(m<0)for(int i:a){m=(i>m)?i:m;m=(i>0)?0:m;}else for(int i:a){m=(i<m)?i:m;m=(i<0)?0:m;}return m;}}

Ungolf it and you get:

int m(int[] a) {
    int m = a[0];
    if (m < 0) {
        for (int i : a) {
            m = (i > m) ? i : m;
            m = (i > 0) ? 0 : m;
        }
    } else {
        for (int i : a) {
            m = (i < m) ? i : m;
            m = (i < 0) ? 0 : m;
        }
    }
    return m;
}

This is a function (if it wasn't pretty damn obvious) that receives an array of numbers and processes its values, returning the minmod value.

My old benemoth of a sollution is also included, which is a whole program - as always.

class M{public static void main(String[]a){java.util.Scanner s=new java.util.Scanner(System.in);int n,m=0;try{m=s.nextInt();if(m<0)while(true){n=s.nextInt();m=(n>m)?n:m;m=(n>0)?0:m;}else while(true){n=s.nextInt();m=(n<m)?n:m;m=(n<0)?0:m;}}catch(java.util.InputMismatchException e){System.out.print(m);}}}

Ungolf it and you get:

class M {

    public static void main(String[] a) {
        java.util.Scanner s = new java.util.Scanner(System.in);
        int n = 0, m = 0;
        try {
            m = s.nextInt();
            if (m < 0) {
                do {
                    n = s.nextInt();
                    m = (n > m) ? n : m;
                    m = (n > 0) ? 0 : m;
                } while (true);
            } else {
                do {
                    n = s.nextInt();
                    m = (n < m) ? n : m;
                    m = (n < 0) ? 0 : m;
                } while (true);
            }
        } catch (java.util.InputMismatchException e) {
            System.out.print(m);
        }
    }
}

Receives infinite numbers, stops when a non-number value is entered, presenting the Minmon value.

Rodolfo Dias

Posted 2014-12-01T15:30:31.490

Reputation: 3 940

Your code seems to discard the first value, so it will give incorrect answers for e.g. 1 2 3. You also seem to be overlooking that you can write a function which processes its arguments rather than a program which reads from stdin. – Peter Taylor – 2014-12-02T16:08:16.570

@PeterTaylor Foolishly, my first instinct is always to write a full program even if it's stated that it can be a function. About that bug, apparently I didn't tested it enough, rats. Will try to correct it now - and make a function-only version as well... – Rodolfo Dias – 2014-12-03T06:49:34.847

2

Game Maker Language, 489 bytes

About Game Maker Language

Riffles the array (zeros are appended) and returns the median (similar to my other answer)

i=0a=argument0
while(variable_local_array_get(a,i))i++
for(j=0;j++;j<i-1)a[j+i]=0var i,j,d,m=0d=ds_list_create()if variable_local_exists(a){if variable_local_array_get(a,0){for(i=0;i<32000;i++){if variable_local_array_get(a,i)=0break
ds_list_add(d,variable_local_array_get(a,i))}ds_list_sort(d,0)i=ds_list_find_value(d,ds_list_size(d) div 2)j=ds_list_find_value(d,(ds_list_size(d) div 2)-1)m=ds_list_find_value(ds,ds_list_size(d) mod 2)ds_list_destroy(d)}if m return (i+j)/2return i
break}

Timtech

Posted 2014-12-01T15:30:31.490

Reputation: 12 038

@MartinBüttner The first 2.5 lines perform the riffle, and the rest finds the median. The 32000 is the maximum size of the array as limited by the software. – Timtech – 2014-12-02T20:12:57.737

@MartinBüttner Yes, within the median part, the whole list is not sorted. – Timtech – 2014-12-02T20:18:18.393

@MartinBüttner it is sorted every iteration... so 3 – Timtech – 2014-12-02T20:24:43.820

Ohhh, I see. That code is surprisingly hard to read for such a wordy language. ^^ – Martin Ender – 2014-12-02T20:25:56.013

@MartinBüttner It's pretty good for golfing (very loose syntax) but it does not contain many standard built-in functions (it is oriented towards game design). – Timtech – 2014-12-02T20:27:13.433

2

R, 20 chars

R is usually not good for codegolf, but I use it for my work so I wanted to try. Before I tried, I didn't know that R is willing to accept such a dirty syntax! :-) 52 chars:

if((q=summary(x))[6]<0)q[6]else if(q[1]>0)q[1]else 0

Then I looked the other answers I tried @xnor's genial median trick, which is great!

median(c(x-x,x)[-1])

Tomas

Posted 2014-12-01T15:30:31.490

Reputation: 2 333

How does your first version work? What does summary do? Are q[1] and q[6] min and max, respectively? In that case, that's not valid, because you can't use built-in min/max. – Martin Ender – 2014-12-03T19:15:39.630

@MartinBüttner it basicly provides a vector of quantiles and a mean. 1 and 6 are 0 and 1 quantiles. I have not used built-in min/max function, as per your rules. – Tomas – 2014-12-03T19:17:09.790

2

Python, 52

I still couldn't help feeling that it's bad to have two lambdas. This function takes in a list and then returns a one-element list containing the result.

f=lambda a:a[1:]and[sorted([a.pop(),0]+f(a))[1]]or a

Hopefully, it will not cause an enormous amount of offense to have the result in a one-element list.

feersum

Posted 2014-12-01T15:30:31.490

Reputation: 29 566

1

Matlab/Octave, 26

This is basically just a translation of the Mathematica answer by xnor. It works by appending one zeros less than the length of the input vector. Note that appending one more would not work, since then the result would be 0 all the time. Thanks to MartinBüttner for the -4 chars of this solution=)

@(x)median([x,0*x(2:end)])

flawr

Posted 2014-12-01T15:30:31.490

Reputation: 40 560

@MartinBüttner You are absolutely right. I now altered it: The program will only append one zero less than the input. This way it is ensured that we have always an odd number of elements and the median takes care fo the rest. – flawr – 2014-12-02T13:22:35.793

or pop the last 0 from your previous solution. – Optimizer – 2014-12-02T13:28:17.187

@MartinBüttner Thanks, of course thats way better. @ Optimizer How would you do that? – flawr – 2014-12-02T13:29:51.847

I have no idea. I thought there must be a way to simply pop off the last element, something like @(x)median([0*x,x](2:end)) . Although it seems like that its the same bytes as now. – Optimizer – 2014-12-02T14:01:46.013

@Optimizer I already thought I missed an important feature of Matlab=) It is too bad that the notation you suggested does not work, it would be really handy sometimes! – flawr – 2014-12-02T15:13:23.840

1

Python, 72 60 bytes

This is the first solution I thought of, and it's quite naive. The second half is basically a duplicate of the first half of the code, but I wasn't sure how to slim it. I wonder if it can be shortened using eval...

Edit: Changed lambdas to comprehensions.

Try them here

lambda l:min(l)*all(x>0for x in l)+max(l)*all(x<0for x in l)

This is only 4 chars longer, but still worth looking at, using Sp3000's TIP.

lambda l:eval("+m%s%s(l)*all(x%s0for x in l)"*2%tuple("ax<in>"))

mbomb007

Posted 2014-12-01T15:30:31.490

Reputation: 21 944

1

Javascript, 63

a=>a.reduce((p,c)=>p<0?c<0?Math.max(p,c):0:c>0?Math.min(p,c):0)

A more readable version:

function (arr) {
    return arr.reduce(function (p, c) {
        if (p < 0) {
            if (c < 0) {
                return Math.max(p, c);
            } else {
                return 0;
            }
        } else {
            if (c > 0) {
                return Math.min(p, c);
            } else {
                return 0;
            }
        }
    });
}

Afonso Matos

Posted 2014-12-01T15:30:31.490

Reputation: 312