非常好的弗里德曼数字


13

弗里德曼号是一个正整数,它等于使用它自己的位结合的操作+,一个非平凡表达- ,*,/,^,括号和级联。

尼斯弗里德曼数是一个正整数,等于一个不平凡的表达式,该表达式使用其自己的数字与相同的运算结合使用,这些数字按其原始顺序排列。

我在这里发明的甚尼斯弗里德曼数(VNFN)是一个尼斯弗里德曼数,可以不用这种表达的不太漂亮的部分来书写(在我看来)。括号,串联和一元取反是不允许的。

对于此挑战,可以使用三种可能的方式编写不带括号的表达式。

前缀:这等效于左联想。这种类型的表达式的所有运算符都写在数字的左侧。每个运算符适用于以下两个表达式。例如:

*+*1234 = *(+(*(1,2),3),4) = (((1*2)+3)*4) = 20

可以这样写的VNFN是343:

^+343 = ^(+(3,4),3) = ((3+4)^3) = 343

后缀:这等效于右联想。就像前缀表示法一样,除了操作在数字的右边。每个运算符都适用于前面的两个表达式。例如:

1234*+* = (1,(2,(3,4)*)+)* = (1*(2+(3*4))) = 14

可以这样写的VNFN是15655:

15655^+** = (1,(5,(6,(5,5)^)+)*)* = (1*(5*(6+(5^5)))) = 15655

中缀:中缀表示法对这五个操作使用标准操作顺序。出于挑战的目的,将按以下方式定义操作顺序:括号^右为第一个,关联为右。然后,将括号括起来*/同时将其左移。最后,将括号括起来+-同时将其左移。

1-2-3 = (1-2)-3 = -4
2/3*2 = (2/3)*2 = 4/3
2^2^3 = 2^(2^3) = 256
1^2*3+4 = (1^2)*3+4 = 7

可以这样写的VNFN是11664:

1*1*6^6/4 = (((1*1)*(6^6))/4) = 11664

挑战:给定一个正整数,如果可以使用前缀,中缀或后缀表示形式将其表示为自己数字的非平凡表达式,则输出该表达式。如果不是,则什么也不输出。

说明:如果可以使用多种表示形式,则可以输出它们的任何非空子集。例如,736是VNFN:

+^736 = 736
7+3^6 = 736

+^7367+3^6或全部都是可接受的输出。

“ Trivial”表达式表示不使用任何运算符的表达式。这仅与一位数字有关,并且意味着一位数字不能为VNFN。这是从弗里德曼数的定义继承的。

对于百万以下的输入,答案应在几秒钟或几分钟之内。

有关。

IO:标准IO规则。完整的程序,功能,动词或类似内容。STDIN,命令行,函数参数或类似参数。对于输出“ Nothing”,空字符串,空行null或类似内容以及空集合都可以。输出可能是用不能以表示形式的字符分隔的字符串,或者可能是字符串的集合。

例子:

127
None

343
^+343

736
736^+
7+3^6

2502
None

15655
15655^+**

11664
1*1*6^6/4
1^1*6^6/4

5
None

计分:这是代码高尔夫球。最少的字节数获胜。

另外,如果找到一个,请在答案中输入新的甚好弗里德曼编号。


*(+(*(1,2),3,4),3
Sparr

“秒或分钟”的上限是多少?..许多...分钟仍在四个小时内。
不是查尔斯(Charles)

@NotthatCharles 4小时太多了。假设我的机器上呆了1个小时,并有一些摆动的空间。关于多位数字,这就是我在“ Parentheses, concatenation and unary negation are disallowed.
isaacg”中

Answers:


5

Perl中,345 334 318 293 263 245B

$_='$_=$i=pop;$c=y///c-1;sub f{say if$c&&$i==eval pop=~s/\^/**/gr}A$m)$1$4"})};f"("x$c.$m}globOx$c.$i;A$1$4($m"})};f$m.")"x$c}glob$i.Ox$c;map{f$_}glob joinO,/./g';s!O!"{+,-,*,/,^}"!g;s!A!'map{m{(\d)((?R)|(\d)(?{$m=$3}))(.)(?{$m="'!ge;s!d!D!;eval

致电 perl -M5.10.0 scratch.pl 736


结果

我发现的前几个结果是:

^+343
736^+
7+3^6
^+/3125
^+^3125
/^+-11664
/^--11664
1-1+6^6/4
/^++14641
^^++14641
1+5^6/1-8
1+5^6^1-8
1+5^6-2-2
1+5^6-2^2
1+5^6+2-4
1+5^6+4^2
-^+^16377
-^-+16377
/^+^16384
/^-+16384

说明

完全没有高尔夫球

我试图尽可能地重复自己,以便以后打高尔夫球更容易。

#!perl
use 5.10.0;

$_ = $input = pop;

# y///c counts characters in $_
$count = y///c - 1;

sub f {
    say if $count && $input == eval pop =~ s/\^/**/gr
}

# PREFIX
map {
    m{                            # Parses *^+1234
        (\D)                      # $1 = first symbol
        (
            (?R)                  # RECURSE
        |
            (\d)(?{               # $3 = first digit
                $match=$3
            })
        )
        (.)(?{                    # $4 = last digit
            $match="$match)$1$4"
        })
    }x;
    f "(" x $count . $match
}
    # glob expands '{0,1}{0,1}' into 00,01,10,11
    glob "{+,-,*,/,^}" x $count . $input;

# POSTFIX
map {
    m{(\d)((?R)|(\d)(?{$match=$3}))(.)(?{$match="$1$4($match"})};
    f $match. ")" x $count
}
    glob $input . "{+,-,*,/,^}" x $count;

# INFIX
# /./g splits $_ into characters
map { f $_} glob join "{+,-,*,/,^}", /./g

打高尔夫球的方式

  • 删除空格和注释,并将所有变量替换为1个字符的版本
  • 在包装程序 $_=q! ... !;eval
  • 提取字符串,然后替换它们。

这给出了类似的内容,您可以从中删除结果的换行符:

$_='
    $_=$i=pop;
    $c=y///c-1;
    sub f{say if$c&&$i==eval pop=~s/\^/**/gr}
    A$m)$1$4"})};f"("x$c.$m}globOx$c.$i;
    A$1$4($m"})};f$m.")"x$c}glob$i.Ox$c;
    map{f$_}glob joinO,/./g
';
s!O!"{+,-,*,/,^}"!g;
s!A!'map{m{(\d)((?R)|(\d)(?{$m=$3}))(.)(?{$m="'!ge;
s!d!D!;
eval

感谢您的回答,并祝贺您排名第一。在广泛的罢工中,它是如何运作的?
isaacg 2015年

我不知道perl,但是看起来可能有可能提取出3个事件}glob并保存一些字节。
isaacg 2015年

s!B!}glob!g;BBB-> 15B;}glob}glob}glob-> 15B :)
亚历山大·布雷特

真是的
isaacg

4

红宝石2.1.5仅- 213 220 238 + 9 = 247

不确定Ruby如何击败Perl,但是您可以...

使用-rtimeout标志(以及-W0或将stderr发送到其他位置)运行此命令。

为了使这稍微更稳健,更换send([].methods[81],z-1)repeated_permutation(z-1)和得分多余字符(这样,248)。

g=$*[0].split //
exit if 2>z=g.size
d=->a,s{$><<a*''&&exit if$*[0].to_i==timeout(2){eval"#{(s*'').gsub(?^,'**')}"}rescue p}
l,r=[?(]*z,[?)]*z
%w{* / + - ^}.send([].methods[81],z-1){|o|d[m=g.zip(o),m]
d[g+o,l.zip(m)+r]
d[o+g,l+g.zip(r,o)]}

基本上,请对运算符进行所有排列,然后按该顺序尝试infix,postfix和prefix。该d方法使用eval第二个参数执行计算,捕获任何DivideByZero或Overflow异常。

不过,您需要将stderr发送到/ dev / null,否则eval有时会显示类似的警告(eval):1: warning: in a**b, b may be too big

当我想出这种方法时,我找到了一种保存三个字符的方法!

空洞的(过时但相似的原则):

input = $*[0]
digits = input.split //
num_digits = digits.size
exit if 2 > num_digits # one-digit numbers should fail

def print_if_eval print_array, eval_array
  # concatenate the array and replace ^ with **
  eval_string = (eval_array * '').gsub(?^, '**') 
  val = eval(eval_string)
  if input.to_i == val
    $><<print_array*''
    exit
  end
rescue
  # this catches any DivideByZero or Overflow errors in eval.
end
# technically, this should be * (num_digits - 1), but as long as we 
# have AT LEAST (num_digits - 1) copies of the operators, this works
operators = %w{* / + - ^} * num_digits
left_parens = ['('] * num_digits
right_parens = [')'] * num_digits
operators.permutation(num_digits-1) { |op_set|
  # infix
  # just uses the native order of operations, so just zip it all together
  # 1+2-3*4/5^6
  print_if_eval(digits.zip(op_set),
                digits.zip(op_set))

  # postfix
  # leftparen-digit-operator, repeat; then add right_parens
  # (1+(2-(3*(4/(5^(6))))))
  # 
  print_if_eval(digits+op_set,
                (left_parens.zip(digits, op_set) + right_parens))

  # prefix
  # leftparens; then add digit-rightparen-operator, repeat
  # ((((((1)+2)-3)*4)/5)^6)
  print_if_eval(op_set+digits,
                left_parens + digits.zip(right_parens, op_set))
}

变更日志

247将该工作用于更大的数目,而不是超时。

220通过声明paren数组削减了三个字符,并修复了将一位数字视为VNFN的错误

213初次提交


很好的解决方案-对我来说完全是黑魔法!我猜ruby击败了Perl,因为它具有内置的zip和置换功能。
亚历山大·布雷特

@ alexander-brett更好吗? a.zip(b,c)返回像这样的数组的数组,[ [a[0],b[0],c[0]],[a[1],b[1],c[1]], etc.]['hi', 'there']*''只是将数组值的字符串表示形式连接起来。
不是查尔斯(Charles)

哦,还有[a,b]*3收益[a,b,a,b,a,b]
不是查尔斯(Charles)

1

MATLAB(435乙)

n=input('');b=str2num(fliplr(num2str(n)));l=floor(log(b)/log(10));a=unique(nchoosek(repmat('*+-/^', 1,5), l), 'rows');for k=1:numel(a(:,1)),for j=0:2,c=strcat((j>1)*ones(l)*'(',mod(b,10)+48);for i=1:l,c=strcat(c,a(k,i),(j<1)*'(',mod(floor(b/10^i),10)+48,(j>1)*')'); end,c=strcat(c,(j<1)*ones(l)*')');if eval(c(1,:))==n,fprintf('%s%s%s%s\n',c(1,1:(j==1)*numel(c(1,:))),fliplr(a(k,1:(j>1)*l)),(j~=1)*num2str(n),a(k,1:(j<1)*l));end,end,end

在这里尝试

http://octave-online.net/


还有更多需要改进的地方
Abr001am,2015年

人们在这里不习惯使用matlab吗?
Abr001am 2015年

0

Python 2,303字节

在线尝试

from itertools import*
n=input()
l=len(n)-1
E=eval
for c in product('+-*/^',repeat=l):
 L=lambda x,y:x.join(map(y.join,zip(n,c+('',)))).replace('^','**')
 C=''.join(c)
 try:
    if`E(L('',''))`==n:print L('','')
    if`E('('*-~l+L('',')'))`==n:print C[::-1]+n
    if`E(L('(','')+')'*l)`==n:print n+C
 except:pass

中缀输出将包含**而不是^。如果不允许这样做,.replace('**','^')则会发生并添加另外的18个字节

说明:

# get all possible combinations of operators (with repetitions)
product('+-*/^',repeat=l)  

# create string from input and operators like
# if passed '(' and '' will return (a+(b+(c
# if passed '' and ')' will return a)+b)+c)
# if passed '' and '' will return a+b+c
lambda x,y:x.join(map(y.join,zip(n,c+('',)))).replace('^','**')

# evaluate infix
E(L('',''))
# evaluate prefix
E('('*-~l+L('',')')) 
# evaluate postfix
E(L('(','')+')'*l)
# all evals need to be inside try-except to handle possible 0 division

# prefix output is need to be swapped (which IMO is not needed)
n:print C[::-1]+n
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.