หมายเลข Friedman ที่ดีมาก


13

ฟรีดแมนจำนวนเป็นจำนวนเต็มบวกที่เท่ากับการแสดงออกที่ไม่น่ารำคาญซึ่งใช้ตัวเลขของตัวเองในการรวมกันกับการดำเนินงาน +, -, *, / ^ วงเล็บและเรียงต่อกัน

Nice Friedman Number เป็นจำนวนเต็มบวกที่เท่ากับนิพจน์ที่ไม่สำคัญซึ่งใช้ตัวเลขของตัวเองร่วมกับการดำเนินการเดียวกันโดยมีตัวเลขตามลำดับดั้งเดิม

หมายเลข Friedman ที่ดีมาก (VNFN) ซึ่งฉันประดิษฐ์ที่นี่คือหมายเลข Nice Friedman ที่สามารถเขียนได้โดยไม่ต้องมีส่วนที่ค่อนข้างน้อย (ในความคิดของฉัน) ในการแสดงออก ไม่อนุญาตให้ใช้วงเล็บ, การต่อกันและการปฏิเสธแบบเอกนารี

สำหรับความท้าทายนี้มีวิธีที่เป็นไปได้สามวิธีในการเขียนนิพจน์โดยไม่มีวงเล็บ

คำนำหน้า:สิ่งนี้เทียบเท่ากับการเชื่อมโยงทางซ้าย ประเภทของนิพจน์นี้เขียนด้วยตัวดำเนินการทั้งหมดทางด้านซ้ายของตัวเลข ตัวดำเนินการแต่ละตัวใช้กับนิพจน์สองข้อต่อไปนี้ ตัวอย่างเช่น

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

VNFN ที่สามารถเขียนด้วยวิธีนี้คือ 343:

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

Postfix:นี่เทียบเท่ากับการเชื่อมโยงทางขวา มันเหมือนกับสัญลักษณ์คำนำหน้ายกเว้นว่าการดำเนินการไปทางขวาของตัวเลข แต่ละโอเปอเรเตอร์ใช้กับนิพจน์ก่อนหน้าทั้งสอง ตัวอย่างเช่น

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

VNFN ที่สามารถเขียนด้วยวิธีนี้คือ 15655:

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

มัด:สัญกรณ์ Infix ใช้คำสั่งมาตรฐานของการดำเนินงานสำหรับการดำเนินงานห้าประการ สำหรับจุดประสงค์ของการท้าทายลำดับการดำเนินการนั้นจะถูกกำหนดไว้ดังนี้: วงเล็บ^ก่อนขวาเชื่อมโยงกัน จากนั้นวงเล็บ*และ/พร้อมกันออกจากกัน ในที่สุดวงเล็บ+และ-พร้อมกันซ้ายเชื่อมโยงกัน

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

ถาม:ได้รับจำนวนเต็มบวกถ้ามันสามารถแสดงเป็นนิพจน์ที่ไม่น่าสนใจของตัวเลขของตัวเองในสัญกรณ์คำนำหน้ามัดหรือ postfix Postfix แสดงออกว่า ถ้าไม่ส่งออกอะไร

การชี้แจง:ถ้าเป็นไปได้หลายตัวแทนคุณอาจส่งออกชุดย่อยที่ไม่ว่างของพวกเขา ตัวอย่างเช่น 736 เป็น VNFN:

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

+^736, 7+3^6หรือทั้งสองทั้งหมดจะเป็นผลที่ยอมรับได้

นิพจน์ "เล็กน้อย" หมายถึงนิพจน์ที่ไม่ได้ใช้โอเปอเรเตอร์ใด ๆ สิ่งนี้เกี่ยวข้องกับตัวเลขหนึ่งหลักเท่านั้นและหมายความว่าตัวเลขหนึ่งหลักไม่สามารถเป็น VNFN ได้ สิ่งนี้สืบทอดมาจากคำจำกัดความของหมายเลขฟรีดแมน

คำตอบควรทำงานในไม่กี่วินาทีหรือนาทีในอินพุตต่ำกว่าหนึ่งล้าน

ที่เกี่ยวข้อง

IO:กฎ IO มาตรฐาน โปรแกรมฟังก์ชั่นเต็มคำกริยาหรือคล้ายกัน STDIN, บรรทัดคำสั่ง, ฟังก์ชั่นการโต้แย้งหรือคล้ายกัน สำหรับการแสดงผล "ไม่มีอะไร" สตริงว่างบรรทัดว่าง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)หายไปหนึ่ง paren ปิดหลังจาก,3
Sparr

ขีด จำกัด "ในไม่กี่วินาทีหรือนาที" คืออะไร สี่ชั่วโมงยังอยู่ใน .... หลายนาที ...
ไม่ใช่ว่า Charles

@NotthatCharles 4 ชั่วโมงมากเกินไป สมมติว่า 1 ชั่วโมงบนเครื่องของฉันกับห้องเลื้อยบาง เกี่ยวกับตัวเลขหลายหลักนั่นคือสิ่งที่ฉันอ้างถึงโดยเรียงต่อกันในParentheses, concatenation and unary negation are disallowed.
isaacg

คำตอบ:


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

คำอธิบาย

ungolfed อย่างเต็มที่

ฉันพยายามทำซ้ำตัวเองให้มากที่สุดเพื่อทำให้การเล่นกอล์ฟในภายหลังง่ายขึ้น

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

มันเป็นอย่างไรของกอล์ฟ

  • ลบ whitespace & ข้อคิดเห็นและแทนที่ vars ทั้งหมดด้วยเวอร์ชัน 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

ฉันไม่ทราบว่า perl แต่ดูเหมือนว่าอาจเป็นไปได้ที่จะแยก 3 เหตุการณ์ที่เกิดขึ้น}globและบันทึกบางไบต์
isaacg

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

สาปเข้ามาใกล้
isaacg

4

Ruby 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 หรือมากเกินใด ๆ

คุณจำเป็นต้องส่ง stderr / dev / null แม้ว่าหรืออื่น ๆ ที่บางครั้งจะพิมพ์คำเตือนเช่นeval(eval):1: warning: in a**b, b may be too big

ในขณะที่ฉันเข้ามากับสิ่งที่ไม่ดีนี้ฉันพบวิธีที่จะช่วยชีวิตสามตัวอักษร!

Ungolfed (หลักการที่ล้าสมัย แต่คล้ายคลึงกัน):

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


ทางออกที่ยอดเยี่ยม - มนต์ดำที่สมบูรณ์สำหรับฉัน! ฉันเดาทับทิมเต้น Perl เพราะมันมีฟังก์ชั่นซิปและการเรียงสับเปลี่ยนในตัว
alexander-brett

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

ลองที่นี่

http://octave-online.net/


จำเป็นต้องมีการปรับปรุงเพิ่มเติม
Abr001am

ผู้คนไม่เคยชินกับ MATLAB ที่นี่ใช่ไหม
Abr001am

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.