Số Friedman rất đẹp


13

Một Số Friedman là một số nguyên dương đó là tương đương với một biểu hiện không tầm thường trong đó sử dụng chữ số riêng của mình trong sự kết hợp với các hoạt động +, -, *, /, ^, dấu ngoặc đơn và nối.

Số Fried Friedman là một số nguyên dương bằng với một biểu thức không tầm thường sử dụng các chữ số của chính nó kết hợp với các hoạt động tương tự, với các chữ số theo thứ tự ban đầu của chúng.

Số Friedman rất đẹp (VNFN), mà tôi đang phát minh ở đây, là Số Friedman đẹp có thể được viết mà không có phần kém đẹp (theo ý kiến ​​của tôi) của một biểu thức như vậy. Dấu ngoặc đơn, nối và phủ định unary không được phép.

Đối với thử thách này, có ba cách viết biểu thức không có dấu ngoặc đơn.

Tiền tố: Điều này tương đương với tính kết hợp trái. Loại biểu thức này được viết với tất cả các toán tử ở bên trái của các chữ số. Mỗi toán tử áp dụng cho hai biểu thức sau. Ví dụ:

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

Một VNFN có thể được viết theo cách này là 343:

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

Postfix: Điều này tương đương với tính kết hợp đúng. Nó giống như ký hiệu tiền tố, ngoại trừ thao tác đi bên phải các chữ số. Mỗi toán tử áp dụng cho hai biểu thức trước. Ví dụ:

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

Một VNFN có thể được viết theo cách này là 15655:

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

Infix: Ký hiệu Infix sử dụng thứ tự hoạt động tiêu chuẩn cho năm thao tác. Đối với các mục đích của thách thức, thứ tự hoạt động đó sẽ được xác định như sau: Dấu ngoặc ^trước, bên phải kết hợp. Sau đó, ngoặc đơn */đồng thời, trái một cách kết hợp. Cuối cùng, ngoặc đơn +-đồng thời, trái một cách kết hợp.

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

Một VNFN có thể được viết theo cách này là 11664:

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

Thách thức: Cho một số nguyên dương, nếu nó có thể được biểu thị dưới dạng một biểu thức không tầm thường của các chữ số của chính nó trong các ký hiệu tiền tố, ký tự hoặc hậu tố, xuất ra biểu thức đó. Nếu không, đầu ra không có gì.

Làm rõ: Nếu có thể có nhiều biểu diễn, bạn có thể xuất bất kỳ tập hợp con không trống nào của chúng. Chẳng hạn, 736 là một VNFN:

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

+^736, 7+3^6Hoặc cả hai tất cả sẽ là kết quả đầu ra chấp nhận được.

Biểu thức "Trivial" có nghĩa là một biểu thức không sử dụng bất kỳ toán tử nào. Điều này chỉ phù hợp với các số có một chữ số và có nghĩa là số một chữ số không thể là VNFN. Điều này được kế thừa từ định nghĩa của Số Friedman.

Câu trả lời sẽ chạy trong vài giây hoặc vài phút trên đầu vào dưới một triệu.

Liên quan.

IO: Quy tắc IO tiêu chuẩn. Chương trình đầy đủ, chức năng, động từ hoặc tương tự. STDIN, dòng lệnh, đối số chức năng hoặc tương tự. Để xuất "Không có gì", chuỗi trống, một dòng trống nullhoặc tương tự và một bộ sưu tập trống đều ổn. Đầu ra có thể là một chuỗi được phân tách bằng một ký tự không thể có trong một biểu diễn hoặc có thể là một tập hợp các chuỗi.

Ví dụ:

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

Ghi điểm: Đây là mã golf. Ít byte nhất sẽ thắng.

Ngoài ra, nếu bạn tìm thấy một, xin vui lòng cung cấp một Số Friedman rất đẹp trong câu trả lời của bạn.


*(+(*(1,2),3,4)đang thiếu một paren gần, sau,3
Sparr

Cái mũ trên "tính bằng giây hay phút" là gì? Bốn giờ vẫn còn trong .... nhiều ... phút.
Không phải Charles

@NotthatCharles 4 giờ là quá nhiều. Giả sử 1 giờ trên máy của tôi, với một số phòng ngọ nguậy. Về các số có nhiều chữ số, đó là những gì tôi đã đề cập đến bằng cách ghép trongParentheses, concatenation and unary negation are disallowed.
isaacg

Câu trả lời:


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

Gọi với perl -M5.10.0 scratch.pl 736


Các kết quả

Một vài kết quả đầu tiên tôi tìm thấy là:

^+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

Giải trình

Hoàn toàn vô dụng

Tôi đã cố gắng lặp lại bản thân nhiều nhất có thể để làm cho việc chơi golf sau này trở nên dễ dàng hơn.

#!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

Làm thế nào nó chơi golf

  • Xóa khoảng trắng và nhận xét và thay thế tất cả các vars bằng phiên bản 1 ký tự
  • Chương trình gói trong $_=q! ... !;eval
  • Trích xuất chuỗi và thay thế chúng sau đó.

Điều này mang lại một cái gì đó như thế này, từ đó bạn có thể loại bỏ các ngắt dòng cho kết quả:

$_='
    $_=$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

Cảm ơn câu trả lời, và chúc mừng bạn đã ở vị trí đầu tiên. Trong các cuộc đình công rộng, làm thế nào nó hoạt động?
isaacg

Tôi không biết perl, nhưng có vẻ như có thể trích xuất 3 lần xuất hiện }globvà lưu một số byte.
isaacg

s!B!}glob!g;BBB-> 15B; }glob}glob}glob-> 15B :)
alexander-brett

Chết tiệt, thật gần.
isaacg

4

Chỉ Ruby 2.1.5 - 213 220 238 + 9 = 247

Không chắc Ruby đánh bại Perl như thế nào, nhưng ở đây bạn đi ...

Chạy cái này với cờ -routout (và -W0 hoặc gửi stderr của bạn ở nơi khác).

Để làm điều này một chút mạnh mẽ hơn, thay thế send([].methods[81],z-1)với repeated_permutation(z-1)và điểm số một nhân vật phụ (như vậy, 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)]}

Về cơ bản, đi qua tất cả các hoán vị của các toán tử và thử infix, postfix và tiền tố theo thứ tự đó. Các dsử dụng phương pháp evaltrên tham số thứ hai để thực hiện các tính toán, đánh bắt bất kỳ trường hợp ngoại lệ DivideByZero hoặc tràn.

Tuy nhiên, bạn cần gửi stderr tới / dev / null, nếu không, evalđôi khi sẽ in cảnh báo như thế nào (eval):1: warning: in a**b, b may be too big.

Trong khi tôi nghĩ ra điều vô căn cứ này, tôi đã tìm ra cách để cứu ba ký tự!

Ungolfed (lỗi thời nhưng nguyên tắc tương tự):

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

Thay đổi

247 làm cho công việc này cho số lượng lớn hơn thay vì hết thời gian.

220 đã loại bỏ ba ký tự bằng cách khai báo mảng paren và sửa một lỗi trong đó các số có một chữ số được coi là VNFN

213 cam kết ban đầu


Giải pháp tuyệt vời - ma thuật đen hoàn chỉnh với tôi! Tôi đoán ruby ​​đánh bại Perl vì nó có chức năng zip và hoán vị tích hợp.
alexander-brett

@ alexander-brett nào tốt hơn? a.zip(b,c)trả về một mảng các mảng như [ [a[0],b[0],c[0]],[a[1],b[1],c[1]], etc.]['hi', 'there']*''chỉ nối chuỗi đại diện của các giá trị mảng.
Không phải Charles

ồ, và [a,b]*3sản lượng[a,b,a,b,a,b]
Không phải Charles

1

MATLAB (435 b)

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

thử nó ở đây

http://octave-online.net/


vẫn còn nhiều cải tiến cần thiết
Abr001am

Mọi người không có thói quen với MATLAB ở đây?
Abr001am

0

Python 2, 303 byte

Dùng thử trực tuyến

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

Đầu ra Infix sẽ chứa **thay vì ^. Nếu điều này không được phép, .replace('**','^')sẽ xảy ra và thêm 18 byte nữa

Giải trình:

# 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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.