স্থায়ীভাবে স্ব-সংশোধনকারী কোড


14

এখন, আমরা সকলেই জানি বেশিরভাগ ভাষায় কোড "স্ব-সংশোধন" করার খুব সহজ উপায় রয়েছে। তবে, আপনি যদি আসলে কোডটি সংশোধন করতে এবং এর কিছু অংশগুলি ডিস্কে সম্পাদনা করতে চান?

আপনার লক্ষ্যটি এমন একটি কোড তৈরি করা যা কোনও নম্বর মুদ্রণ করে, তারপরে তার নিজের ফাইলটি সম্পাদনা করে ফাইবোনাকি অনুক্রমের মতো পরবর্তী নম্বরটির সাথে নম্বরটি প্রতিস্থাপন করতে:

$ ./program
1
$ ./program
1
$ ./program
2
$ ./program
3
$ ./program
5
[etc...]

বিধি

  1. আপনি কোডের "বাইরের" নম্বর (গুলি) না সঞ্চয় করতে পারেন। কোনও মন্তব্য নেই, স্ক্রিপ্টটি প্রস্থান করতে বলা হচ্ছে না, কোনও ইওএফ ইত্যাদি নেই
  2. যদি আপনার কোড কোনও ফাইলের সাথে কাজ করে তবে আপনার বাইট পরিমাণ থেকে ২ টি বিয়োগ করুন $BYTESNOW ($ORIGINALBYTES - 2)এবং আপনার শিরোনামে লিখুন । (ফাইলের নামগুলি যে কোনও বর্ণানুক্রমিক ফাইল পাথের মধ্যে রয়েছে বলে ধরে নেওয়া হয়))
  3. আপনার কোড অবশ্যই কোনও বাহ্যিক পাইপ সহায়তা ছাড়াই ফাইলটিতে আউটপুট লিখতে হবে।
  4. আপনার কোড এক বা শূন্য থেকে শুরু করতে পারেন। এটা কোন ব্যাপার না।

8
পরের বার, দয়া করে পরিবর্তে আপনার ধারণাটি স্যান্ডবক্সে পোস্ট করুন এবং প্রতিক্রিয়া পেতে কিছু দিন সেখানে পোস্টটি রেখে দিন।
জংহওয়ান মিন

2
প্রোগ্রামিং ভাষার দোভাষী (উদাঃ perl6 program) এর সাহায্যে প্রোগ্রামটি কল করার অনুমতি দেওয়া হয় , অথবা এটিতে শেবাং লাইনটি অন্তর্ভুক্ত করতে হবে যাতে এটি হিসাবে পরিচিত ./program?
22:38

1
এছাড়াও, আমরা যদি -2 বাইট বোনাসের জন্য যেতে না চাই, আমরা কি একটি একক বাইট ফাইলের নাম চয়ন করতে পারি বা এটির থাকতে হবে program, এবং আমরা কি এটি বর্তমান কার্যনির্বাহী ডিরেক্টরিতে অনুমান করতে পারি?
22:44

যখন বিপুল সংখ্যক সুস্পষ্টভাবে সূচকীয় স্বরলিপিতে রূপান্তর শুরু করে, তখনও এটি ব্যর্থ হওয়ার অনুমতি দেওয়া যেতে পারে?
প্যাট্রিক রবার্টস

কেন কেবল 2 বাইট বোনাস? সর্বাধিক ভাষা, উদাহরণস্বরূপ। লুয়া, এর "a"পরিবর্তে এটি করা সহজ করুন arg[0]। এটি তার পক্ষে উপযুক্ত বলে মনে হচ্ছে না।
এ্যাটাকো

উত্তর:


7

ব্যাশ, 52 47 (49-2) বাইট

সম্পাদনাগুলি:

  • 0 এর পরিবর্তে 1 দিয়ে শুরু করে 5 বাইট সংরক্ষণ করা হয়েছে! ধন্যবাদ লিও!

Golfed

A=$[1+0]
echo $A
sed -ri "s/\w+\+(\w+)/\1+$A/" $0

পরীক্ষা

>for i in `seq 10`
> do
> ./fibo
> done
1
1
2
3
5
8
13
21
34
55

2
আমি মনে করি আপনি [-1 + 1] এর পরিবর্তে [1 + 0] থেকে শুরু করে 1 বাইট সংরক্ষণ করতে পারবেন (চ্যালেঞ্জের চতুর্থ নিয়ম দেখুন)
লিও

2
প্রকৃতপক্ষে, এটি আপনাকে -?রেজেক্স থেকে অপসারণ করে আরও বেশি বাইট সংরক্ষণ করবে । এবং যেহেতু আপনি সেখানে আছেন, আপনি প্রথম ক্যাপচারিং
লিও

@ লিও এটি একটি দুর্দান্ত পরামর্শ, আপনাকে ধন্যবাদ!
জেপেলিন

2

পাইথন 2, 118 111 বাইট (113 - 2)

a,b=0,1;print a
f=open(__file__,'r+')
s=f.read()
s=s.replace(s[4:s.find(';')],`b`+','+`a+b`)
f.seek(0)
f.write(s)

এটি কোনও বৈধ ফাইল নাম সহ কাজ করে। এখানে ব্যাখ্যা করার মতো অনেক কিছুই নেই, কোডটি নিজেই খুব ভার্বোজ।

আমাকে স্মরণ করিয়ে দেওয়ার জন্য ফ্লিপট্যাককে ধন্যবাদ , close()বাধ্যতামূলক নয়।


1
আপনি কি শুধু বক্তব্যের f=open(...)পরিবর্তে ব্যবহার করতে পারবেন না with?
ফ্লিপট্যাক

2

ব্যাচ, 81 বাইট

@call:c
@set/az=x+y
@echo %x%
@echo>>%0 @set/ax=%z%,y=%x%
:c
@set/ax=0,y=1

দ্রষ্টব্য: পিছনের নতুন লাইনটি তাৎপর্যপূর্ণ। স্ক্রিপ্টটি এক্সটেনশন সহ পুরো নাম ব্যবহার করে আহ্বান করা প্রয়োজন। আউটপুট 0 থেকে শুরু হয়।

ব্যাচ যেহেতু বাস্তবসম্মতভাবে কোনও ফাইল সম্পাদনা করতে পারে না, তাই আমি কেবল ফাইলের শেষের দিকে অতিরিক্ত লাইন যুক্ত করি, সুতরাং শেষ পর্যন্ত এটি জানতে পারবে যে পরবর্তী সংখ্যাটি মুদ্রণ করতে হবে। >>%0বসানো একটি বাইট কারণ আমি এটা কোনো সংখ্যা দিয়ে আগে বসতে পারেনা পরিমাণ সঞ্চয় হয়।


1

সি, 142 বাইট (144 - 2)

void main(int x,char**a){FILE*f=fopen(*a,"r+");fseek(f,27,0);char n=fgetc(f),m=fgetc(f);fseek(f,27,0);printf("%d\n",fputc(fputc(m,f)?n+m:1,f));}

এটি বেশ সোজা এগিয়ে। প্রথমে এটি পরে দুটি অক্ষর 0x1A অবস্থানের শিরোনামে সংরক্ষণ করে reads আমি ডেটা সংরক্ষণের জন্য নিরাপদ স্পটটি খুঁজে পেতে আরও গভীরভাবে দেখতে পারতাম তবে এটি আমার মেশিনে ওএসএক্স চালিত আমার পক্ষে কাজ করে, জিসিসি ৪.২িশ দিয়ে সংকলিত এবং আমি সন্দেহ করি যে এটি খুব বহনযোগ্য। এছাড়াও, যেহেতু এটি অক্ষরের বাইরে রয়েছে 13 তম পুনরাবৃত্তির পরে এটি উপচে পড়েছে।

এটি আউটপুট দেয়:

1
1
2
3
5
8
13
21
34
55

1

নোড.জেএস, 152 137 বাইট (139 - 2)

স্পষ্টতার জন্য নতুন লাইনের সাথে পৃথক করা, বাইট গণনার অংশ নয়।

f=_=>require('fs').writeFileSync(__filename,
`f=${f};f()`.replace(/(\d[^,]*),(\d[^\)]*)/,
(m,a,b)=>`${b=+b},${+a+b}`),console.log((0,1)));
f()

ব্যাখ্যা:

f=_=>                          // define `f` as function with a single unused argument `_`
  require('fs').writeFileSync( // import the standard filesystem module and overwrite file
    __filename,                // string var containing path of file for current module
    `f=${f};f()`.replace(      // template string containing source of entire script
      /(\d[^,]*),(\d[^\)]*)/,  // regexp to match and group the numbers in this script
      (m,a,b)=>                // replace function with arguments match, group a, group b
        `${b=+b},${+a+b}`      // template string incrementing fibonacci numbers in place
    ),                         // end replace()
    console.log(               // prints to stdout, `undefined` passed to argument
      (0,1)                    // comma separated group returns value of last expression
    )                          // end console.log()
  )                            // end fs.writeFileSync()
;                              // end statement defining `f` as arrow function
f()                            // run function to modify script and print fibonacci number

ব্যবহার:

// assuming above script is stored in program.js
$ node program
1
$ node program
1
$ node program
2
$ node program
3
$ node program
5
...

1

পাইথন 3.6, 96 91 (93-2) বাইট

a,b=0,1
f=open(__file__,"r+");next(f);f.write(f"a,b={b,a+b}\n{next(f)}{f.seek(0)}");print(b)

ফাইলের নাম হার্ডকোডিং করলে 5 বাইট (88 বাইট) বাঁচানো যায়:

a,b=0,1
f=open("f","r+");next(f);f.write(f"a,b={b,a+b}\n{next(f)}{f.seek(0)}");print(b)

কিছু কিছু বাইট সংরক্ষণ করেছেন @ আর্টায়ারকে ধন্যবাদ


1
এটি সম্পর্কে (88 বাইট)a,b=0,1 f=open('f','r+');next(f);f.write(f'a,b={b,a+b}\n{next(f)}{f.seek(0)}');print(b)#
আরটিয়ার 23'17

1

বাশ + ইউনিক্স ইউটিলিটিস, 43 বাইট (45-2)

dc -e9k5v1+2/z^5v/.5+0k1/p;sed -i s/z/z1+/ $0

প্রথমবার এটি চালিত হওয়ার পরে, এটি বিনেট সূত্রের মাধ্যমে 1 ম ফিবোনাচি নম্বর গণনা করতে ডিসি ব্যবহার করে। সেডের প্রতিটি কলই ডিসি পাস করা স্ট্রিং পরিবর্তন করে প্রোগ্রামটি পরিবর্তন করে; এই পরিবর্তন ডিসিকে সূত্রে অতিরিক্ত 1 যোগ করতে বলে, যার ফলে এটি প্রতিবার ফাইওনাচি অনুক্রমের পরবর্তী সংখ্যাটি গণনা করে।

পরীক্ষা

> for k in {1..10}
> do
> ./fib
> done
1
1
2
3
5
8
13
21
34
55

এটি কীভাবে কাজ করে তা চিত্রিত করতে, এই মুহুর্তে, 55 টি মুদ্রণের পরে, প্রোগ্রামটি পড়তে পরিবর্তন করা হয়েছে:

dc -e9k5v1+2/z1+1+1+1+1+1+1+1+1+1+^5v/.5+0k1/p;sed -i s/z/z1+/ $0

সুতরাং এটি আবার চালানোর ফলন

> ./fib
89

এবং প্রোগ্রামটি এখন পড়ে:

dc -e9k5v1+2/z1+1+1+1+1+1+1+1+1+1+1+^5v/.5+0k1/p;sed -i s/z/z1+/ $0

আমি এই পছন্দ! সাবাশ !
জেপেলিন

@ জেপেলিন আপনাকে ধন্যবাদ - এটি আমাদের পূর্ববর্তী সংস্করণটির সাথে সমস্যাগুলি এড়িয়ে চলে।
মিশেল স্পেক্টর

1

স্মাইলব্যাসিক 3, 99 বাইট (101 -2)

-2 বাইট বোনাস কারণ এটি কোনও ফাইলের সাথে কাজ করে।

A=0B=1F$="TXT:"+PRGNAME$()S$=LOAD(F$)SAVE F$,SUBST$(S$,0,INSTR(S$,"F"),FORMAT$("A=%DB=%D",B,A+B))?A+B

এই এক কাজ করে, এবং এটি একরকম আমার ভাঙ্গা হিসাবে একই আকার হয়ে শেষ!


আপনি যদি বোনাস না করেন তবে এটি আরও খাটো
12

একটি নির্দিষ্ট ফাইলের নাম জোর করা আমাকে একটি ফ্রিকের মতো মনে করে। আমি যাই হোক না কেন এই উত্তরগুলির অর্ধেকটি প্রহার করছি
শামুক_ফেব্রুয়ারি

আমি মনে করি লোড ডায়ালগটি বন্ধ না করা আরও খারাপ।
12Me21

এটি যদি আপনি স্লট 1 এ লোড করেন এবং PRGEDITপ্রথম লাইনটি প্রতিস্থাপন করতে কমান্ডগুলি ব্যবহার করেন (এবং এর পরে একটি লাইনব্রেক যুক্ত করুন A=0B=1) এবং আপনার A=0প্রথমবারের প্রয়োজনও নেই ।
12Me21

0

আর, 145 বাইট (147 - 2)

a=c(1,1)
cat(a[1])
R=readLines(f<-sub("^.+=","",grep("^--f",commandArgs(F),v=T)))
cat(c(sprintf("a=c(%i,%i)",a[2],sum(a)),R[-1]),file=f,sep="\n")

(একটি পেছনের নিউলাইন রয়েছে)। এটি কোনও বৈধ ফাইল নামের সাথে কাজ করে।


0

পার্ল 6 , 67 62 বাইট (64 - 2)

say (1,1,*+*...*)[1];$*PROGRAM.&{.spurt: .slurp.&{S/\[<(\d+/{$/+1}/}}

say 0+1;$*PROGRAM.&{.spurt: .slurp.&{S/(\d+).(\d+)/$1+{$0+$1}/}}

0

স্ট্যাকড, নন-কেপটিং, 65 (67 - 2) বাইট

ফাইল আইও সম্পর্কিত কয়েকটি সমস্যা কমিটের সর্বাধিক সাম্প্রতিক সিরিজে স্থির করা হয়েছিল। সুতরাং, নন-কেপটিং।

2:>
:sum\tail...\stack:0#out repr LF+program LF split last+d0\write

এখানে গিথুবের একটি লিঙ্ক।

উদাহরণ কার্যকর

(আমি স্পষ্টতার জন্য আসল পথ বাদ দিয়েছি))

C:\
λ type permanently-self-modifying-code.stk
2:>
:sum\last\stack:0#out repr LF+program LF split last+d0\write
C:\
λ stacked permanently-self-modifying-code.stk
1

C:\
λ stacked permanently-self-modifying-code.stk
1

C:\
λ stacked permanently-self-modifying-code.stk
2

C:\
λ stacked permanently-self-modifying-code.stk
3

C:\
λ stacked permanently-self-modifying-code.stk
5

C:\
λ stacked permanently-self-modifying-code.stk
8

ব্যাখ্যা

ক্রমটি শুরু করতে একজোড়া সংখ্যার সংখ্যা নিয়ে কীভাবে এটি কাজ করে ( 2:>এই ক্ষেত্রে পূর্ণসংখ্যার পরিসর [0, 2), যা এটি (0 1)), তারপরে তাদের উপর ফিবোনাকির রূপান্তর সম্পাদন করে:

:sum\last\                     top of stack: (x y)
:              duplicate.             stack: ((x y) (x y))
 sum           sum of TOs.            stack: ((x y) x+y)
    \          swap order.            stack: (x+y (x y))
     last      obtain last element.   stack: (x+y y)
         \     swap order.            stack: (y x+y)

প্রতিটি রানেই, এই রূপান্তরটি স্ট্যাকের শীর্ষে কার্যকর করা হয়। তারপরে, স্ট্যাকটি স্ট্যাকের দিকে ঠেলাঠেলি করা হয়, সদৃশ হয়ে যায় এবং এর প্রথম সদস্য প্রাপ্ত হয় ( stack:0#)। এই আইটেমটি তারপরে আউটপুট করা হয় এবং এটি পছন্দসই ফিবোনাচি নম্বর। reprতারপরে স্ট্যাকের উপস্থাপনা নেয় এবং একটি নতুন লাইন সংযোজন করে। তারপরে, প্রোগ্রামটি স্ট্যাকের দিকে ঠেলে দেওয়া হয় এবং নতুন লাইনে বিভক্ত হয়। তারপরে, আমরা শেষ সদস্যটি (শেষ লাইন) নিই এবং এটি পূর্বোক্ত স্ট্রিংয়ে যুক্ত করব। শেষ অবধি, আমরা চাপ দিই d0(ফাইলটি নিজেই; ভাবুন dওলারের চিহ্ন 0== $0।) এবং এটিতে লিখি।



0

ক্লোজার, 209 204 195 বাইট

0 1(let[u #(apply str %)a"./src/s.clj"p #(Long/parseLong(u %))l(fn[v](split-with #(Character/isDigit %)v))c(slurp a)[n[_ & r]](l c)[m r](l r)b(+(p n)(p m))](println b)(spit a(str(p m)" "b(u r))))

-5 বাইটগুলি সংখ্যার পরিবর্তে পূর্ণসংখ্যার পরিবর্তে দীর্ঘ সংখ্যাগুলিতে পার্স করে, এবং কয়েকটি মিস স্পেসগুলি সরিয়ে।

দ্বিতীয় নম্বর এবং (let...)(এখন পর্যন্ত সবচেয়ে ব্যয়বহুল স্থান!) এর মধ্যে স্থানটি সরিয়ে -9 বাইট

একটি বিবরণের জন্য প্রিগল্ফড কোড মন্তব্যগুলি দেখুন।

আবার পরীক্ষা করা হয়েছে এবং এটি আর তুলনামূলক বন্ধনী ত্রুটি নিক্ষেপ করে না। এটি 7540113804746346429 পর্যন্ত কাজ করে, যে সময়ে এটি একটি পূর্ণসংখ্যার ওভারফ্লো ব্যতিক্রম ছোঁড়ে।

এছাড়াও নোট করুন, এটি ধরে নেয় উত্স কোডটি "./src/s.clj" এ অবস্থিত।

0 1 ; Starting numbers
(let [; The first 4 entires are shortcuts to functions and data that are used more than once
      u #(apply str %) ; Turns a list into a string
      a "./src/s.clj" ; Current location
      p #(Integer/parseInt (u %)) ; Integer parsing shortcut
      ; Used to split a string on digits to parse them out
      l (fn [v] (split-with #(Character/isDigit %) v))
      src (slurp a) ; Get the source
      [n [_ & r]] (l src) ; Use deconstructuring to grab the first number
      [m r] (l r) ; Same as above, grabbing the second number
      n' (+ (p n) (p m)) ; Parse the 2 numbers, and add them
      ; Put everything back together, only this time with the new numbers
      k (str (p m) " " n' (u r))]
  (println n') ; Print the new number
  (spit a k)) ; Overwrite the old source
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.