23
\$\begingroup\$

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>

\$\endgroup\$
13
  • 1
    \$\begingroup\$ Maybe add a column for how many answers are there in each language \$\endgroup\$ Commented Dec 1, 2014 at 21:45
  • 1
    \$\begingroup\$ @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. ;) \$\endgroup\$ Commented Dec 1, 2014 at 21:48
  • 1
    \$\begingroup\$ @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.) \$\endgroup\$ Commented Dec 2, 2014 at 10:09
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – Optimizer
    Commented Dec 2, 2014 at 11:12
  • 2
    \$\begingroup\$ @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. \$\endgroup\$ Commented Dec 2, 2014 at 12:39

24 Answers 24

24
+100
\$\begingroup\$

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).

\$\endgroup\$
13
\$\begingroup\$

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

\$\endgroup\$
3
  • \$\begingroup\$ Cool, our answers are less than 1 second apart, which means my answer used to be the shortest. ;) \$\endgroup\$
    – Timtech
    Commented Dec 2, 2014 at 0:02
  • 1
    \$\begingroup\$ +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.) \$\endgroup\$ Commented Dec 2, 2014 at 0:03
  • \$\begingroup\$ What the...well, there is always LOTS of stuff to lean :O \$\endgroup\$ Commented Dec 6, 2014 at 23:42
11
\$\begingroup\$

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

\$\endgroup\$
1
  • \$\begingroup\$ Rare for Haskell to be this golfable (and, ironically, still readable). Love it. \$\endgroup\$
    – Claudia
    Commented Dec 3, 2014 at 22:08
10
\$\begingroup\$

JavaScript (ES6), 39 bytes

a=>a.reduce((p,c)=>p*c>0?p*p>c*c?c:p:0)
\$\endgroup\$
1
7
\$\begingroup\$

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

\$\endgroup\$
6
\$\begingroup\$

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])
\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Dec 1, 2014 at 20:54
  • \$\begingroup\$ Your latter approach is now valid, too. \$\endgroup\$ Commented Dec 1, 2014 at 23:20
6
\$\begingroup\$

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

\$\endgroup\$
1
  • \$\begingroup\$ I have implemented a TIS emulator for TIO, so you can now try it online! \$\endgroup\$
    – Phlarx
    Commented May 2, 2018 at 20:00
5
\$\begingroup\$

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(#)
\$\endgroup\$
3
  • \$\begingroup\$ \a-> (signum a,a) is the same as signum>>=(,) using the function monad instance. (see my post in "tips for golfing in haskell") \$\endgroup\$ Commented Dec 1, 2014 at 17:07
  • \$\begingroup\$ Thanks for the tip, but it's now moot. :) \$\endgroup\$
    – Zgarb
    Commented Dec 1, 2014 at 18:11
  • \$\begingroup\$ @Zgarb Ah okay. \$\endgroup\$
    – Optimizer
    Commented Dec 2, 2014 at 12:47
4
\$\begingroup\$

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.

\$\endgroup\$
3
  • \$\begingroup\$ 25 bytes: q~_{g}%_|:+\{z\za+_~>=}**. \$\endgroup\$
    – jimmy23013
    Commented Dec 1, 2014 at 17:34
  • \$\begingroup\$ Fails for single int array. I tried it too :) \$\endgroup\$
    – Optimizer
    Commented Dec 1, 2014 at 17:36
  • \$\begingroup\$ Although there is a 26 byte solution in there . Thanks for that :) \$\endgroup\$
    – Optimizer
    Commented Dec 1, 2014 at 17:38
4
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ I have much to learn yet. +1. \$\endgroup\$ Commented Dec 3, 2014 at 8:35
4
\$\begingroup\$

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.

\$\endgroup\$
4
\$\begingroup\$

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
\$\endgroup\$
5
  • 3
    \$\begingroup\$ Interesting way of counting code size... \$\endgroup\$
    – Ypnypn
    Commented Dec 2, 2014 at 2:22
  • 3
    \$\begingroup\$ @Ypnypn turns out, we're fine with it, though \$\endgroup\$ Commented Dec 2, 2014 at 10:20
  • \$\begingroup\$ 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... \$\endgroup\$
    – lirtosiast
    Commented May 20, 2015 at 18:18
  • \$\begingroup\$ You are right. It looks like that bumps my code size from 12 to 15 bytes. \$\endgroup\$
    – Timtech
    Commented Jul 8, 2015 at 20:00
  • \$\begingroup\$ I guess you're right. +4 bytes there. \$\endgroup\$
    – Timtech
    Commented Jul 9, 2015 at 20:44
3
\$\begingroup\$

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

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

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.

\$\endgroup\$
1
  • \$\begingroup\$ Perhaps something like {asc[0,x,y]1}/? \$\endgroup\$ Commented Dec 3, 2014 at 9:41
3
\$\begingroup\$

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
\$\endgroup\$
2
  • \$\begingroup\$ No need of tQ. Q will also work \$\endgroup\$
    – Optimizer
    Commented Dec 1, 2014 at 17:55
  • \$\begingroup\$ Quite right! I also think I can remove one of the ? for a *... \$\endgroup\$ Commented Dec 1, 2014 at 17:56
3
\$\begingroup\$

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);}}}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ There's no need to handle empty input, as I didn't even define the function for that case. \$\endgroup\$ Commented Dec 2, 2014 at 17:46
3
\$\begingroup\$

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.

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

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}
\$\endgroup\$
5
  • \$\begingroup\$ @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. \$\endgroup\$
    – Timtech
    Commented Dec 2, 2014 at 20:12
  • \$\begingroup\$ @MartinBüttner Yes, within the median part, the whole list is not sorted. \$\endgroup\$
    – Timtech
    Commented Dec 2, 2014 at 20:18
  • \$\begingroup\$ @MartinBüttner it is sorted every iteration... so 3 \$\endgroup\$
    – Timtech
    Commented Dec 2, 2014 at 20:24
  • \$\begingroup\$ Ohhh, I see. That code is surprisingly hard to read for such a wordy language. ^^ \$\endgroup\$ Commented Dec 2, 2014 at 20:25
  • \$\begingroup\$ @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). \$\endgroup\$
    – Timtech
    Commented Dec 2, 2014 at 20:27
2
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Dec 2, 2014 at 16:08
  • \$\begingroup\$ @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... \$\endgroup\$ Commented Dec 3, 2014 at 6:49
2
\$\begingroup\$

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])
\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Dec 3, 2014 at 19:15
  • \$\begingroup\$ @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. \$\endgroup\$
    – Tomas
    Commented Dec 3, 2014 at 19:17
2
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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)])
\$\endgroup\$
5
  • \$\begingroup\$ @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. \$\endgroup\$
    – flawr
    Commented Dec 2, 2014 at 13:22
  • \$\begingroup\$ or pop the last 0 from your previous solution. \$\endgroup\$
    – Optimizer
    Commented Dec 2, 2014 at 13:28
  • \$\begingroup\$ @MartinBüttner Thanks, of course thats way better. @ Optimizer How would you do that? \$\endgroup\$
    – flawr
    Commented Dec 2, 2014 at 13:29
  • \$\begingroup\$ 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. \$\endgroup\$
    – Optimizer
    Commented Dec 2, 2014 at 14:01
  • \$\begingroup\$ @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! \$\endgroup\$
    – flawr
    Commented Dec 2, 2014 at 15:13
1
\$\begingroup\$

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>"))
\$\endgroup\$
1
\$\begingroup\$

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;
            }
        }
    });
}
\$\endgroup\$

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