এই সমস্যার খাঁটি-কার্যকরী সমাধান কি অতীব প্রয়োজনীয় হিসাবে পরিষ্কার হতে পারে?


10

পাইথনে আমার নিম্নরূপ অনুশীলন আছে:

  • বহুবর্ষটি গুণফলগুলির একটি দ্বিগুণ হিসাবে দেওয়া হয় যাতে শক্তিগুলি সূচকগুলি দ্বারা নির্ধারিত হয়, যেমন: (9,7,5) মানে 9 + 7 * x + 5 * x ^ 2

  • প্রদত্ত এক্স এর মান গণনা করতে একটি ফাংশন লিখুন

যেহেতু আমি ইদানীং ক্রিয়ামূলক প্রোগ্রামিংয়ে আছি, তাই আমি লিখেছি

def evaluate1(poly, x):
  coeff = 0
  power = 1
  return reduce(lambda accu,pair : accu + pair[coeff] * x**pair[power],
                map(lambda x,y:(x,y), poly, range(len(poly))),
                0)

যা আমি অপঠনযোগ্য বলে মনে করি, তাই আমি লিখেছিলাম

def evaluate2(poly, x):
  power = 0
  result = 1
  return reduce(lambda accu,coeff : (accu[power]+1, accu[result] + coeff * x**accu[power]),
                poly,
                (0,0)
               )[result]

যা কমপক্ষে অপঠনযোগ্য তাই আমি লিখেছি

def evaluate3(poly, x):
  return poly[0]+x*evaluate(poly[1:],x) if len(poly)>0 else 0

যা কম দক্ষ হতে পারে (সম্পাদনা করুন: আমি ভুল ছিলাম!) যেহেতু এটি ক্ষয়ক্ষতির পরিবর্তে বহু গুণ ব্যবহার করে, নীতিগতভাবে, আমি এখানে পরিমাপের বিষয়ে চিন্তা করি না (সম্পাদনা করুন: আমার কত নির্বোধ! পরিমাপ করা আমার ভুল ধারণাটি চিহ্নিত করেছিল!) এবং এখনও পুনরাবৃত্ত সমাধান হিসাবে পঠনযোগ্য (তর্কযোগ্যভাবে) না:

def evaluate4(poly, x):
  result = 0
  for i in range(0,len(poly)):
      result += poly[i] * x**i
  return result

অপরিহার্য হিসাবে পাঠযোগ্য এবং দক্ষতার সাথে এটির কাছাকাছি কোনও বিশুদ্ধ-কার্যকরী সমাধান রয়েছে কি?

স্বীকার করা, একটি প্রতিনিধিত্বমূলক পরিবর্তন সাহায্য করবে, কিন্তু এটি অনুশীলন দ্বারা দেওয়া হয়েছিল।

হাস্কেল বা লিস্প পাশাপাশি হতে পারে, কেবল পাইথন নয়।


7
আমার অভিজ্ঞতার সাথে, পারস্পরিক পরিবর্তনশীল ভেরিয়েবলগুলি ব্যবহার না করার অর্থে বিশুদ্ধভাবে কার্যকরী কোড (যা forলুপগুলি ব্যবহার না করে বোঝায় , উদাহরণস্বরূপ) পাইথনের লক্ষ্য নির্ধারণ করা একটি খারাপ লক্ষ্য। পরিবর্তনশীলগুলিকে বিচারযোগ্যভাবে পুনরায় বাঁধাই করা এবং অবজেক্টগুলি পরিবর্তিত না করা আপনাকে প্রায় সমস্ত সুবিধা দেয় এবং কোড অসীমভাবে আরও পঠনযোগ্য করে তোলে। যেহেতু সংখ্যার অবজেক্টগুলি অপরিবর্তনীয় এবং এটি কেবল দুটি স্থানীয় নাম পুনরায় প্রত্যাবর্তন করে, আপনার "অপরিহার্য" সমাধানটি কোনও "কঠোরভাবে বিশুদ্ধ" পাইথন কোডের চেয়ে কার্যকরী প্রোগ্রামিংয়ের গুণাবলীকে আরও ভালভাবে উপলব্ধি করে।

2
বিটিডব্লিউ গুন পদ্ধতিটি হর্ণারের পদ্ধতি এবং এটি প্রতিটি পদক্ষেপে ক্ষয়ক্ষতির চেয়ে বেশি দক্ষ, কারণ ক্ষতিকারকটির জন্য খুব একই গুণ এবং তার পরে আরও কিছু প্রয়োজন।

1
lambdaহালকা বেনামি সিনট্যাক্স ফাংশনটির সাথে ভাষার তুলনা করার সময় পাইথন কৃপণভাবে কুৎসিত হয়। এর একটি অংশ সম্ভবত "অপরিষ্কার" চেহারাতে অবদান রাখে।
কেচালাক্স

@ কেচালাক্স ঠিক এটিই বলছিলাম। কার্যকরী প্রোগ্রামিং সমর্থনটি পাইথনে কিছুটা ক্ষেত্রে চিন্তাভাবনা এবং এটি এক প্রকারের শো। তবুও আমি মনে করি না যে প্রথম সংস্করণটি এত ভয়াবহভাবে অপঠনযোগ্য যে আপনি কী বুঝতে পারছেন না।
এভিকাটোস

আমি আপনার কোড দ্বারা সত্যই বিভ্রান্ত হয়েছি, যদিও সমস্যা-স্কোপের একটি গাণিতিক সমীকরণ রয়েছে যা অত্যন্ত স্পষ্ট, আপনি কেন কেবল সেই গণিতের সমীকরণ ভারব্যাটিয়াম ব্যবহার করবেন না? এটি যে কোনও ভাষা দিয়ে মোটামুটি সহজেই কোনও ফাংশনে রূপান্তরিত হয়েছে ... আপনি যখন কোনও একক সমীকরণকে মূল্যায়ন করে যে সমীকরণটি প্রশ্নটি জিজ্ঞাসা করছেন তখন আপনি কী কী মানচিত্র বা হ্রাস বা পুনরুক্তি করতে চান তা নিশ্চিত নন - এটি জিজ্ঞাসা করে না মোটেও পুনরাবৃত্তি ...
জিমি হোফা

উত্তর:


13

@ ডেলানান উল্লেখ করেছেন যেহেতু হর্নারের পদ্ধতিটি সম্ভবত আরও বেশি গণনামূলকভাবে দক্ষ, তবে আমি ক্ষয়ক্ষতির সমাধানের জন্য পাইথনে এটি সুন্দর পাঠযোগ্য বলে ডাকব:

def eval_poly(poly, x):
    return sum( [a * x**i for i,a in enumerate(poly)] )

17
বর্গাকার বন্ধনীগুলি ফেলে দিন এবং ভেরিয়েবলগুলিকে আরও বর্ণনামূলক নাম দিন এবং এটি আরও ভাল: sum(coeff * X**power for power, coeff in enumerate(poly))
ইজকাটা

1
এটি আমাকে দুঃখ দেয় যে অন্যান্য পোস্ট উত্তরগুলি এত জটিল। আপনার সুবিধার জন্য ভাষাটি ব্যবহার করুন!
ইজকাটা

বোধগম্য ফাংশনাল প্রোগ্রামিং-এ লুপ "পাচারের মতো"
ব্যবহারকারী 1358

7
@ user1358 না, এটা রচনা জন্য অন্বিত চিনি mapএবং filter। এটিকে কেউ একটি নির্দিষ্ট আকারের লুপের জন্যও ভাবতে পারে তবে সেই আকারের লুপগুলি উল্লিখিত ফ্যানসিটোনাল সংযুক্তকারীটির সমতুল্য।

7

অনেকগুলি কার্যকরী ভাষায় ম্যাপি বাস্তবায়ন রয়েছে যা আপনাকে মানচিত্রের মাধ্যমে সূচি বুনতে দেয়। যোগফলের সাথে এটি একত্রিত করুন এবং আপনার F # তে নিম্নলিখিতটি রয়েছে:

let compute coefficients x = 
    coefficients 
        |> Seq.mapi (fun i c -> c * Math.Pow(x, (float)i))
        |> Seq.sum

2
এমনকি যদি না হয় তবে যতক্ষণ আপনি বুঝতে পারবেন যে কীভাবে mapকাজ করে, আপনার নিজের একটি লিখতে এটি বেশ সহজ হওয়া উচিত।
কেচালোক্স

4

আপনার কোডটি আপনার সংজ্ঞায়িত সমস্যার ক্ষেত্রের সাথে কীভাবে সম্পর্কযুক্ত তা আমি বুঝতে পারি না, তাই আমি আপনার কোডটি সমস্যার সুযোগটিকে উপেক্ষা করে কী করে তার সংস্করণ দেব (আপনি লিখেছেন এমন আবশ্যক কোডের ভিত্তিতে)।

খুব পঠনযোগ্য হাস্কেল (এই পদ্ধতির সহজেই যে কোনও এফপি ভাষায় অনুবাদ করা যায় যা তালিকা তৈরির তালিকা রয়েছে এবং খাঁটি এবং পঠনযোগ্য বেরিয়ে আসে):

eval acc exp val [] = acc
eval acc exp val (x:xs) = eval (acc + execPoly) (exp+1) xs
  where execPoly = x * (val^exp)

কখনও কখনও এফপিতে অভ্যস্ত লোকদের কাছে আরও সংক্ষিপ্ত পদ্ধতির চেয়ে হ্যাশেলের মতো নিষ্পাপ সাধারণ পদ্ধতির চেয়ে পরিচ্ছন্ন।

আরও পরিস্কারভাবে আবশ্যক পদ্ধতি যা এখনও সম্পূর্ণ শুদ্ধ:

steval val poly = runST $ do
  accAndExp <- newSTRef (0,1)
  forM_ poly $ \x -> do
    modifySTRef accAndExp (updateAccAndExp x)
  readSTRef accAndExp
  where updateAccAndExp x (acc, exp) = (acc + x*(val^exp), exp + 1)

দ্বিতীয় পদ্ধতির বোনাসটি এসটি মোনাডে চলছে এটি খুব ভাল সম্পাদন করবে।

যদিও নিশ্চিত হওয়া যায়, হাসকলারের কাছ থেকে সম্ভবত সম্ভবত বাস্তবায়ন হ'ল উপরের অন্য উত্তরে উল্লিখিত জিপবিথ। zipWithএকটি খুব সাধারণ পদ্ধতির এবং আমি বিশ্বাস করি পাইথন ফাংশন এবং ম্যাপ করা যায় এমন একটি সূচকের সংমিশ্রণের জন্য জিপিং পদ্ধতির নকল করতে পারে।


4

আপনার যদি কেবল একটি (স্থির) টিউপল থাকে তবে কেন এটি (হাসকেলে) করবেন না:

evalPolyTuple (c, b, a) x = c + b*x + a*x^2

পরিবর্তে আপনার সহগের একটি তালিকা থাকলে আপনি ব্যবহার করতে পারেন:

evalPolyList coefs x = sum $ zipWith (\c p -> c*x^p) coefs [0..]

বা আপনি যেমনটি করেছিলেন তেমন হ্রাস সহ:

evalPolyList' coefs x = foldl' (\sum (c, p) -> sum + c*x^p) 0 $ zip coefs [0..]

1
এটি হোমওয়ার্ক নয়! আমি ইতিমধ্যে 3 টি সমাধান করেছি তা উল্লেখ করার দরকার নেই।
ব্যবহারকারী1358

পাইথনের অর্ধেক সময় (এই ক্ষেত্রে অন্তর্ভুক্ত), "টিপল" এর অর্থ "অপরিবর্তনীয় তালিকা" এবং এ কারণে নির্বিচারে দৈর্ঘ্য।

স্পষ্টতই নির্বিচারে দৈর্ঘ্য
ব্যবহারকারী 1358

1
পাইথনের কারণে নয়, তবে
বহুবর্ষটি

1
@ ডেলান এটি আকর্ষণীয় আমি সর্বদা tupleমানগুলির একটি স্থির-আকারের সেটকে বোঝাতে চেয়েছি, প্রতিটি সম্ভাব্য বিবিধ প্রকারের, যা এগুলিতে যুক্ত বা সরানো যায় না। আমি কখনই বুঝতে পারি না কেন তালিকাগুলি সহ একটি গতিশীল ভাষা, যা ভিন্নজাতীয় ইনপুট গ্রহণ করে, তাদের প্রয়োজন হবে কেন।
কেচালাক্স

3

কার্যকরী অ্যালগরিদমের পাঠযোগ্যতা উন্নত করতে আপনি কয়েকটি ধাপের সেট ব্যবহার করতে পারেন:

  • সমস্ত কিছুকে এক লাইনে ক্র্যাম করার চেষ্টা না করে আপনার মধ্যবর্তী ফলাফলগুলিতে নাম রাখুন।
  • ল্যাম্বডাসের পরিবর্তে নামযুক্ত ফাংশনগুলি ব্যবহার করুন, বিশেষত ভার্বোস ল্যাম্বদা সিনট্যাক্স সহ ভাষাগুলিতে। evaluateTermলম্বা ল্যাম্বডা এক্সপ্রেশনের মতো কিছু পড়া খুব সহজ । আপনি যেহেতু ল্যাম্বডা ব্যবহার করতে পারেন তার অর্থ এটি আপনার প্রয়োজন হওয়া উচিত নয়
  • যদি আপনার এখন-নামক ফাংশনগুলির মধ্যে এমন কোনও কিছু মনে হয় যা প্রায়শই ঘনিয়ে আসে তবে সম্ভাব্যতা এটি ইতিমধ্যে স্ট্যান্ডার্ড লাইব্রেরিতে রয়েছে। চারপাশে তাকাও. আমার পাইথন একটু মরিচা, কিন্তু আপনি মূলত reinvented মত দেখে মনে হচ্ছে enumerateবা zipWith
  • প্রায়শই, নামকৃত কার্যকারিতা এবং মধ্যবর্তী ফলাফলগুলি কী ঘটছে সে সম্পর্কে যুক্তিযুক্তকরণ এবং এটি সরলকরণকে সহজ করে তোলে, যার ফলে এটি একটি ল্যাম্বডাকে পিছনে রাখা বা কিছু লাইন একসাথে আবার একত্রিত করার অর্থ হতে পারে।
  • লুপের জন্য যদি অপরিহার্যভাবে আরও পঠনযোগ্য মনে হয় তবে সম্ভাবনাগুলি একটি বোধগম্যতা ভালভাবে কাজ করবে।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.