最短Minmod函数


24

minmod功能是熟悉的一种变型分钟,出现在偏微分方程斜率限制性高分辨率方案。给定许多坡度,它会选择最平坦的坡度,同时注意坡度之间的相对符号。

该函数接受任意数量的参数。然后将minmod(x 1,x 2,...,x n定义为:

  • min(x 1,x 2,...,x n,如果所有x i都严格为正
  • max(x 1,x 2,...,x n,如果所有x i均为负
  • 0,否则。

我们将仅考虑整数输入,因为这实际上不会影响实现,并且对于某些(深奥)语言应具有更大的包容性。

编写程序或函数,该程序或函数通过STDIN,ARGV或函数参数(如果要比可变参数函数更方便,则可以使用数组)接收n个有符号整数(对于n> 0),然后返回或打印(到STDOUT)结果的minmod(a,b)

您一定不能使用内置的minmax函数(显然,如果可以实际找到的话,也没有内置的minmod)。此外,固定的少量项目(少于5个)进行分类外,不得使用任何内置的分类功能。

如果您的语言没有带符号的类型,则可以使用无符号的类型并将其解释为二进制补码。例如,如果您的语言仅使用无符号字节,则可以使用255代表-1128代表-128,等等。

这是代码高尔夫球,因此最短的答案(以字节为单位)获胜。

测试用例

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

排行榜

以下堆栈摘录按语言生成常规排行榜和获胜者概述。因此,即使您选择的语言不能让您赢得全部挑战,为什么不尝试在第二名中夺取一席之地呢?

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

# Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以通过打败旧分数保持标题。例如:

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


1
也许要增加一列以每种语言显示多少个答案
骄傲的haskeller 2014年

1
@proudhaskeller嗯,我喜欢当前两个表可以放在一起而不打开全屏显示的片段-我认为如果再增加一列会太挤。如果您的评论获得的支持远远超过我的支持,那么我会做的。;)
Martin Ender 2014年

1
@Optimizer我认为以前版本的规则对人们答案的创造力造成的伤害比我预期的要大。此外,无论如何,在规则更改之前,我将奖励悬赏领先的答案,因此我也不认为对rep造成任何损害。(是的,我同意规则更改不是一个好主意,但我认为在这种情况下这是值得的。)
Martin Ender 2014年

1
@MartinBüttner-我现在在新答案中看不到任何创造力。一切都归结为成对的最小模数。创造力来自xnor的答案或Mig的方法,许多其他答案都影响到了创造力。
Optimizer

2
@Optimizer,并非总能说出新答案是否与旧答案完全一样的创意,或者它是否是一个没有想象力的端口。
彼得·泰勒

Answers:


13

GolfScript,10 9个字节

~{0]$1=}*

假设标准输入来自标准输入 [-4 -2 -3 -2]

这使用了内置的sort函数$,但是每次调用它时,它都是在3个元素的数组上,这是允许的。

在线演示


太棒了,我们的答案间隔不到1秒,这意味着我的答案过去最短。;)
Timtech

1
+1,这比我的解决方案更短,更聪明。(注:如果有人对此表示怀疑,是的,此解决方案是正确的,并且可以通过归纳法很容易地证明。Peter的代码所做的是重复计算前一个minmod值,下一个输入值和零的中值;可能的情况表明,这确实产生了新的minmod值。)
Ilmari Karonen 2014年

什么...好吧,总是有很多东西要瘦:O
TheBlastOne 2014年

24

Mathematica,19个字节

Median[#~Riffle~0]&

编码和打高尔夫球感谢MartinBüttner。

这是一个未命名的纯函数,它将整数列表作为输入。像这样调用

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

或类似地保存到变量。

代码首先在输入列表的每两个元素之间对一个零进行零码处理,然后n-1n元素之间插入零。然后,需要中位数来产生答案。

这给出了min-mod,因为它可以处理每种情况:

  1. 所有数字都是正数,在这种情况下,零在它们之下,并且中位数是最低的正数。

  2. 所有数字均为负数,在这种情况下,零在其上方,并且中位数是最小的负数。

  3. 既有正数也有负数,因此中间元素为零。

如果Mathematica使用线性时间选择算法来实现其中值,那么它也是O(n)。


11

Haskell,62 61 39 38 37字节

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

使用从@Zgarb的答案*借来的一些比较魔术,即x*x<=x*y

x*x<=x*y仅当xy具有相同的符号并且y的绝对值较大时才为true 。注意,当x0它始终是真实的。

我们确定x它是包含在中的结果s,并且所有yin s x的符号都与相同,y并且绝对值较小。如果没有值s满足此定义,0则为结果。

f然后通过搜索s满足此要求的元素来工作,并0用作默认值。

*尽管出于我使用它的原因他没有使用它,但实际上他现在已经摆脱了它


Haskell很难成为这种高尔夫(并且具有讽刺意味的是,仍然可读)。爱它。
伊赛亚·梅多斯


6

Python 2,53

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

这个想法是用来reduce将两输入的min-mod查找器变成一输入的n。我独立于使用它的其他答案提出了它。仅Python 2支持reduce

双输入解决方案仅查找两个数字和零的中位数。有关使用中位数的更直接方法,请参阅我的Mathematica答案

少打高尔夫球:

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

Python 2和Python 3中的假想汞合金将是一个字符短,与加星号的分配从Python 3中和input(),并print在Python 2。

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

旧代码,不进行排序:

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

嗯,是的,同时我注意到了这种副作用,但是我觉得现在解决这个问题为时已晚。Mathematica具有内置功能Median
Martin Ender 2014年

您的后一种方法现在也有效。
Martin Ender 2014年

6

Marbelous,210个字节

@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
\/

这里使用三块板。

|板(Ab在可读版本)采用大理石的绝对值(通过返回所传递的大理石或零减去传递大理石,如在Marbelous所有算术是无符号的)。

M板(Minabs在可读版本)查找并输出到左边或者通过所述第一或第二大理石(两者具有更小的绝对值),并且如果一个不同的签名的大理石被传递离开。

M板还释放其持有的大理石,而不是向下向左一次从标准输入的最后一个字符是牵强。

M板在主板上用于在任何给定时间存储所有检查值的minmod,因为它释放了要向左保存的值,然后将其偏转回去。

垃圾桶(\/)仅放置在同步器下,否则将打印到STDIN。

输入/输出使用STDIN / STDOUT。两者都处理8位值(如果您想传递+ 0x30和+ 0x38,则08放入STDIN)。

库和圆柱板都是必需的。建议以十进制数查看输出(请注意,这将显示minmod结果的无符号值)。

在这里测试。

注意:要获得更人性化的输入/输出,请Dp在主板的最后一行(之前:M)添加,替换]]Rd,并在底部添加以下内容:

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

这只是将输出更改为3个十进制数字。同样,进行这些更改的输入也需要一个空格分隔的列表,每个数字3个十进制数字。

可读版本:

板子图片


5

Haskell,83 40 39字节

这可能不是最短的Haskell解决方案(并且肯定不会在这里击败其他解决方案),但这只是一个开始。编辑:现在缩短了50%以上!EDIT2:少一个字节...

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

这只是一个简单的倍(或减少,因为某些语言称呼它)由二元运算符#,其计算的位数ab0。即使规则现在允许我对小列表进行排序,但这也需要在Haskell中进行导入,并导致更高的字节数(49个字节,但不导入则为31个字节):

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

\a-> (signum a,a)signum>>=(,)使用函数monad实例相同。(请参阅我的文章“在
Haskell

感谢您的提示,但现在没有实际意义。:)
Zgarb 2014年

@Zgarb啊,好的。
Optimizer

5

TIS-100, 696个 526字节

@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

期望序列以终止-999。TIS-100比这个问题要新,但是无论如何这不是很重要。

节点9跟踪我们是正面的,负面的还是混合的。节点5和6会查找所有输入数字的绝对值的最小值。然后,节点10根据节点9的状态选择最小值,取反的最小值或0。

在此处输入图片说明


我已经为TIO实现了TIS仿真器,因此您现在可以在线尝试!
Phlarx

4

CJam,20个字节(或10个字节)

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

使用@xnor的方法,减少从数组中一次计算2个数字的minmod。

这将是19个字节,如果:z工作


使用对短数组使用排序的新规则:

q~{0]$1=}*

这完全等同于@Peter的答案


前26个字节字节:

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

这可以打更多...

输入(通过STDIN)是整数数组,例如:

[-4 -2 -3 -2]

输出是输入数组的minmod

在这里尝试

如果只是:g:z工作,这将是4个字节短。


25个字节:q~_{g}%_|:+\{z\za+_~>=}**
jimmy23013 2014年

单int数组失败。我也尝试过:)
Optimizer

尽管那里有一个26字节的解决方案。谢谢您:)
Optimizer

4

Java,84个字节

这是Java的全部荣耀。比GolfScript差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;}

上课包装:

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;}

}

扩展了注释:

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;
    }

}

注意:这可以使用Java 8进行改进。

注意:在Java 8中进行改进的努力失败。


我还有很多东西要学。+1。
Rodolfo Dias 2014年

4

J,20 12字节

以列表为参数的函数。从Golfscript / CJam /任何地方窃取。

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

的minmod x并且y是中位数(排序/:~,取出中间1{)三个项目列表0,x,y。减少清单(折叠在相邻元素之间使用此minmod来以J说法)。

在REPL中使用。(J拼写其负号_。)

   (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

旧垃圾,之前我注意到各种短允许:0:`<.`>.@.(*@]*0<*))/的minmod xy0( 0:)如果0大于或等于产品xy,否则它是分(<.)或MAX( >.)之间x,并y取决于标志。将其折叠在整个列表上。


4

TI-BASIC,19字节

假定输入格式为{-2,4,3}

与xnor的答案类似:

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

3
计算代码大小的有趣方式...
Ypnypn 2014年


我的代码median(augment(Ans,0ΔList(Ans(只有八个字节)在维度一的列表上失败。 If variance(Ans:augment(Ans,0ΔList(Ans:median(Ans比您的更长。如果仅TI-BASIC支持空列表...
lirtosiast,2015年

你是对的。看起来这使我的代码大小从12个字节增加到15个字节。
Timtech

我想你是对的。那里+4个字节。
Timtech

3

Python 2,82 79 71 69 61字节

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

这是根据我的pyth答案得出的,该答案是受Mig的答案启发


旧答案:

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

这是一个很长的答案。我觉得拥有2个变量很浪费...?我是对的...?会吗?; p


3

KDB / Q,用于功能体定义的43个字符

感谢以前的帖子中的好主意:

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

使用登记输入单个号码

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]

我确定某些Q大师可以提出更短的Q。


也许像{asc[0,x,y]1}/
algorithmhark

3

Pyth,25 22 20 12

uhtS[0GH)QhQ

可能不是新颖的,但原创的:P


允许预分类

u*?Gx>GH>G0H>*GHZQhQ

腐霉菌

在线尝试。

使用想法reduce和三元声明从Mig的答案中被偷偷偷偷地偷了,但是我不知道这些算法是否在其他方面甚至都相似,因为我看不懂三元语句。

说明:

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

不需要tQQ也将起作用
Optimizer

非常正确!我也认为我可以删除其中?一个*...
FryAmTheEggman 2014年

3

C#,101个字节

我第一次尝试打高尔夫球,并以一种漂亮的打高尔夫的恶意语言。基于reduce(Aggregate在LINQ中),与Mig的JavaScript答案非常相似。可以像运行(new System.Linq.M()).m(new[] {1, 2, 3})。通过所有测试用例,但不处理空的输入数组。

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);}}}

1
无需处理空输入,因为我什至没有为这种情况定义函数。
Martin Ender 2014年

3

J,12个字节

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

该函数/使用以下表达式简化列表(在J中称为folding()):

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

[x,y][abs(x)>abs(y)]y,如果abs(x) > abs(y)别的x

例:

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

在这里在线尝试。


2

游戏制作者语言,489字节

关于游戏制作者语言

排列数组(附加零)并返回中位数(类似于我的其他答案)

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}

@MartinBüttner前2.5行执行浅滩,其余的找到中位数。的32000是为限于由软件阵列的最大大小。
Timtech

@MartinBüttner是的,在中间部分内,整个列表未排序。
Timtech

@MartinBüttner,它会在每次迭代时进行排序...所以3
Timtech,2014年

哦,我明白了。对于这种冗长的语言,该代码令人惊讶地难以阅读。^^
Martin Ender 2014年

@MartinBüttner这对高尔夫相当不错(非常松散的语法),但它不包含许多标准的内置功能(它面向游戏设计)。
Timtech

2

Java中,353 304 124字节

将最差的代码高尔夫语言与世界上最糟糕的高尔夫球手放在一起,您将获得...

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;}}

取消高尔夫,您将获得:

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;
}

这是一个函数(如果不是很明显),它接收数字数组并处理其值,并返回minmod值。

一如既往,我也包括了我的解决方案,这是一个完整的程序。

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);}}}

取消高尔夫,您将获得:

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);
        }
    }
}

接收无限数字,当输入非数字值并显示Minmon值时停止。


您的代码似乎放弃了第一个值,因此它将为例如提供错误的答案1 2 3。您似乎也忽略了您可以编写一个处理其参数的函数,而不是编写一个从stdin读取程序的函数。
彼得·泰勒

@PeterTaylor愚蠢地,即使声明它可以是一个函数,我的第一个直觉总是写一个完整的程序。关于那个错误,显然,我没有对它进行足够的测试,老鼠。现在将尝试纠正它-并制作仅功能的版本...
Rodolfo Dias 2014年

2

R,20个字符

R通常不适用于代码高尔夫,但是我在工作中使用了R,所以我想尝试一下。在尝试之前,我不知道R是否愿意接受这种肮脏的语法!:-) 52个字符

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

然后我看了尝试@xnor的一般中位数技巧的其他答案,这太棒了!

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

您的第一个版本如何运作?怎么summary办?分别是q[1]q[6]最小值和最大值?在这种情况下,这是无效的,因为您不能使用内置的最小/最大。
Martin Ender 2014年

@MartinBüttner它基本上提供了分位数和均值的向量。1和6是0和1分位数。根据您的规则,我没有使用内置的最小/最大功能。
托马斯2014年

2

Python,52岁

我仍然忍不住觉得有两个lambda秒很不好。该函数接收一个列表,然后返回包含结果的单元素列表。

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

希望它不会导致将大量结果包含在一个元素列表中。


1

Matlab /八度,26

这基本上只是xnor对Mathematica答案的翻译 它通过在输入向量的长度后面附加一个零来工作。请注意,再添加一个将不起作用,因为那样的话,结果始终都是0。感谢MartinBüttner提供此解决方案的-4个字符=)

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

@MartinBüttner你绝对正确。现在,我对其进行了更改:该程序将仅比输入少添加一个零。这样可以确保我们总是有奇数个元素,其余部分由中位数负责。
瑕疵的

或从上一个解决方案中弹出最后一个0。
Optimizer

@MartinBüttner谢谢,那当然更好。@ Optimizer您将如何做?
瑕疵的

我不知道。我认为必须有一种方法可以简单地弹出最后一个元素,例如@(x)median([0*x,x](2:end))。尽管看起来它的字节数与现在相同。
Optimizer

@Optimizer我已经以为我错过了Matlab的重要功能=)太糟糕了,您建议的符号不起作用,有时真的很方便!
瑕疵的

1

Python,72 60字节

这是我想到的第一个解决方案,非常幼稚。后半部分基本上是代码前半部分的副本,但是我不确定如何精简它。我想知道是否可以使用eval... 来缩短它

编辑:将lambdas更改为理解。

在这里尝试

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

使用Sp3000的时间仅增加4个字符,但仍然值得一看 TIP

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

1

Javascript,63

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

更具可读性的版本:

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;
            }
        }
    });
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.