কতবার পুনরাবৃত্তি ফাংশন ডাকা হয়েছিল তা ট্র্যাক করে রাখুন


62

 function singleDigit(num) {
      let counter = 0
      let number = [...num + ''].map(Number).reduce((x, y) => {return x * y})

      if(number <= 9){
          console.log(number)
      }else{
          console.log(number)
          return singleDigit(number), counter += 1
      }
   }
singleDigit(39)

উপরের কোডটি একটি পূর্ণসংখ্যা নেয় এবং এটি তার নিজস্ব অঙ্কগুলি দ্বারা গুণ করে একক অঙ্কে হ্রাস করে।

উদাহরণ 39।

3 x 9 = 27.
2 x 7 = 14.
1 x 4 = 4.

কনসোলটি লগ করবে:

27 
14 
4

আমি কীভাবে ট্র্যাক রাখতে পারি যে পুনরাবৃত্ত ফাংশনটি 3 বার বলা হয়েছিল?

আমি একটি কাউন্টার যুক্ত করার চেষ্টা করেছি তবে এটি আপডেট করতে ব্যর্থ। কোন সাহায্য প্রশংসা করবে


4
.map(Number)অপ্রয়োজনীয় যেহেতু *অপারেটর যেভাবেই মানগুলিতে সংখ্যায় জোর করে। ;-)
রবিজি

4
দু'একটি প্রশ্ন: ১) নেতিবাচক সংখ্যার সাথে ডিল করার বিষয়ে আপনি কীভাবে মনস্থ করেন? উদাহরণস্বরূপ, সংখ্যাটি -57সত্যই একটি -50এবং একটি -7.. যখন এই দিকে তাকানো হয়, এটি -5x এর একটি হ্রাস করবে যাতে -7ইতিবাচক সংখ্যা পাওয়া যায় 35। অথবা আপনি এটির সাথে কেবল নেতিবাচক চিহ্নটি দেখতে চান 5এবং এটি নয় 7, এমনকি 7এটি আসলে নেতিবাচকও রয়েছে। ২) আপনি শূন্য অন্তর্ভুক্ত সংখ্যার সাথে কীভাবে আচরণ করবেন? এটি স্বয়ংক্রিয়ভাবে হ্রাস শূন্য হবে। অতএব, আপনি যে বৃহত সংখ্যায় পাস করবেন, এটি তত বেশি শূন্য হয়ে যাবে। অন্য বিকল্পটি
হ'ল

3
আমি বুঝতে পারি আমার উপরের প্রশ্নগুলি পুনরাবৃত্তি গণনা সম্পর্কে নয়, বরং এই প্রশ্নটিতে ব্যবহৃত সামগ্রীর ধাঁধা সমাধানের দিক। অনুগ্রহ করে আমাকে ক্ষমা করবেন.
পিম্প ট্রাইস্কিট

3
আপনি আমার উত্তর পছন্দ করেছেন তা নিয়ে আমি চাটুকার, তবে ব্যবহারিক উদ্দেশ্যে, আমি মনে করি স্ট্যাকওভারফ্লো.com/a/59570894/1346276 সবচেয়ে সাধারণ সাধারণ রূপ।
phipsgabler

2
@pshipgabler যে কেউ বুদ্ধিমান এবং সুসংগত উত্তর লেখার জন্য সময় নেয় সে পছন্দ মত প্রাপ্য। আপনাকে ধন্যবাদ
chs242

উত্তর:


25

এটি প্রায় খাঁটি একাডেমিক বৈকল্পিক, তবে আপনি এই উদ্দেশ্যে একটি পরিবর্তিত স্থির বিন্দু সংযোজক ব্যবহার করতে পারেন ।

আপনার মূল ফাংশনটি কিছুটা সংক্ষিপ্ত ও উন্নত করতে দেয়:

function singleDigit(n) {
    let digitProduct = [...(n + '')].reduce((x, y) => x * y, 1);
    return digitProduct <= 9 ? digitProduct : singleDigit(digitProduct);
}

// singleDigit(123234234) == 0

এই বৈকল্পিক থেকে, আমরা পুনরাবৃত্ত কলকে ফ্যাক্ট আউট এবং কারি করতে পারি:

function singleDigitF(recur) {
    return function (n) {
        let digitProduct = [...(n + '')].reduce((x, y) => x * y, 1);
        return digitProduct <= 9 ? digitProduct : recur()(digitProduct);
    };
}

এই ফাংশনটি এখন একটি নির্দিষ্ট পয়েন্ট সমন্বয়কারী ব্যবহার করা যেতে পারে; বিশেষত আমি নীচে জাভাস্ক্রিপ্টের জন্য (কড়া) অভিযোজিত ওয়াই কম্বিনেটরটি প্রয়োগ করেছি:

function Ynormal(f, ...args) {
    let Y = (g) => g(() => Y(g));
    return Y(f)(...args);
}

যেখানে আমরা আছে Ynormal(singleDigitF, 123234234) == 0

এখন কৌশল আসে। যেহেতু আমরা ওয়াই সংযোজককে পুনরাবৃত্তিটি ফ্যাক্টর করেছি তাই আমরা এর মধ্যে পুনরাবৃত্তির সংখ্যাটি গণনা করতে পারি:

function Ycount(f, ...args) {
    let count = 1;
    let Y = (g) => g(() => {count += 1; return Y(g);});
    return [Y(f)(...args), count];
}

নোড REPL এ একটি দ্রুত চেক দেয়:

> Ycount(singleDigitF, 123234234)
[ 0, 3 ]
> let digitProduct = (n) => [...(n + '')].reduce((x, y) => x * y, 1)
undefined
> digitProduct(123234234)
3456
> digitProduct(3456)
360
> digitProduct(360)
0
> Ycount(singleDigitF, 39)
[ 4, 3 ]

এই সংযুক্তকারীটি এখন স্টাইলে লিখিত যে কোনও পুনরাবৃত্ত ফাংশনে কলগুলির সংখ্যা গণনা করার জন্য কাজ করবেsingleDigitF

(নোট করুন যে খুব ঘন ঘন উত্তর হিসাবে শূন্য পাওয়ার দুটি উত্স রয়েছে: সংখ্যার ওভারফ্লো ) ( 123345456999999999হয়ে যাওয়া 123345457000000000ইত্যাদি), এবং ইনপুটটির আকার যখন বৃদ্ধি পাচ্ছে তখন আপনি মাঝারি মানের হিসাবে প্রায় অবশ্যই শূন্য পাবেন)


6
নিম্নগামীদের কাছে: আমি সত্যিই আপনার সাথে একমত হই যে এটি সর্বোত্তম ব্যবহারিক সমাধান নয় - সে কারণেই আমি এটিকে "বিশুদ্ধভাবে একাডেমিক" হিসাবে উপস্থাপন করেছি।
phipsgabler

সত্য, এটি একটি দুর্দান্ত সমাধান এবং মূল প্রশ্নের রিগ্রেশন / ম্যাথ টাইপের জন্য সম্পূর্ণ উপযুক্ত।
শেরফ

73

আপনার ফাংশন সংজ্ঞায় আপনার পাল্টা যুক্তি যুক্ত করা উচিত:

function singleDigit(num, counter = 0) {
    console.log(`called ${counter} times`)
    //...
    return singleDigit(number, counter+1)
}
singleDigit(39)

6
অসাধারণ. দেখে মনে হচ্ছে আমার কাউন্টারটি কাজ করছে না কারণ আমি এটিকে
ফাংশনটিতে

7
@ chs242 স্কোপ বিধিগুলি আদেশ করে যে ফাংশনে এটি ঘোষণার মাধ্যমে প্রতিটি আহবান একটি নতুন তৈরি করবে। stackoverflow.com/questions/500431/...
Taplar

10
@ chs242 এমন নয় যে আপনি এটি ফাংশনের মধ্যেই ঘোষণা করেছেন। প্রযুক্তিগতভাবে এটি সমস্ত ডিফল্ট প্যারামিটারগুলিও কাজ করে চলেছে - আপনার ক্ষেত্রে এটি কেবল সহজ যে ফাংশনটি পুনরাবৃত্তভাবে বলা হওয়ার পরে পরবর্তী সময়ে কখনই মানটি নিয়ে যায় না। এএই প্রতিবার ফাংশনটি রান counterহয়ে যায় এবং সেট হয়ে যায় 0, যদি না আপনি স্পষ্টভাবে আপনার পুনরাবৃত্ত কলটিতে শেরেফের মতো না চালিয়ে যান। AesingleDigit(number, ++counter)
zfrisch

2
ডান @zfrisch আমি এখন বুঝতে পারি। এটি ব্যাখ্যা করার জন্য সময় দেওয়ার জন্য ধন্যবাদ
chs242

35
দয়া করে এতে পরিবর্তন ++counterকরুন counter+1। এগুলি কার্যকরীভাবে সমতুল্য, তবে পরবর্তীকালের উদ্দেশ্যটি আরও ভালভাবে সুনির্দিষ্ট করে, (অকারণে) মিউটেট এবং প্যারামিটারটি করে না এবং ঘটনাক্রমে পোস্ট-ইনক্রিমেন্টের সম্ভাবনাও নেই। বা আরও ভাল, যেহেতু এটি একটি টেল-কল, পরিবর্তে একটি লুপ ব্যবহার করুন।
ব্লুরাজা - ড্যানি পিফ্লুঘুফ্ট

37

Traditionalতিহ্যগত সমাধানটি হ'ল একটি উত্তর হিসাবে প্রস্তাবিত হিসাবে ফাংশনটির প্যারামিটার হিসাবে গণনাটি পাস করা।

তবে, জেএসে আরও একটি সমাধান রয়েছে। আরও কয়েকটি উত্তর কেবল পুনরাবৃত্ত ফাংশনের বাইরে গণনা ঘোষণা করার পরামর্শ দেয়:

let counter = 0
function singleDigit(num) {
  counter++;
  // ..
}

এটি অবশ্যই কাজ করে। তবে এটি ফাংশনটিকে অ-প্রতীক্ষিত করে তোলে (দু'বার সঠিকভাবে বলা যাবে না)। কিছু ক্ষেত্রে আপনি এই সমস্যাটিকে উপেক্ষা করতে পারেন এবং কেবল এটি নিশ্চিত করতে পারেন যে আপনি singleDigitদু'বার কল করবেন না (জাভাস্ক্রিপ্ট একক থ্রেডযুক্ত তাই করা খুব বেশি কঠিন নয়) তবে এটি একটি বাগ যা অপেক্ষাকৃত singleDigitঅপ্রত্যাশিত হওয়ার পরে আপডেট করলে তা হওয়ার অপেক্ষা রয়েছে এবং এটি অনুভবও করে কুশ্রী।

সমাধানটি counterবিশ্বব্যাপী নয়, পরিবর্তকের বাইরে ঘোষণা করা। এটি সম্ভব কারণ জাভাস্ক্রিপ্টের বন্ধ রয়েছে:

function singleDigit(num) {
  let counter = 0; // outside but in a closure

  // use an inner function as the real recursive function:
  function recursion (num) {
    counter ++
    let number = [...num + ''].map(Number).reduce((x, y) => {return x * y})

    if(number <= 9){
      return counter            // return final count (terminate)
    }else{
      return recursion(number)  // recurse!
    }
  }

  return recursion(num); // start recursion
}

এই সর্বব্যাপী সমাধান কিন্তু প্রতিটি সময় আপনি কল অনুরূপ singleDigit(যা এখন না একটি recursive ফাংশন) এটি একটি নতুন দৃষ্টান্ত তৈরি করবে counterপরিবর্তনশীল।


1
কাউন্টার ভেরিয়েবলটি কেবলমাত্র singleDigitফাংশনের মধ্যেই উপলব্ধ এবং কোনও যুক্তি ইমো পাস না করে এটি করার একটি বিকল্প পরিষ্কার উপায় সরবরাহ করে। +1
অ্যান্ড্রুL64

1
যেহেতু recursionএখন সম্পূর্ণ বিচ্ছিন্ন তাই শেষ প্যারামিটার হিসাবে কাউন্টারটি পাস করা সম্পূর্ণ নিরাপদ হওয়া উচিত। আমি মনে করি না যে কোনও অভ্যন্তরীণ ফাংশন তৈরি করা প্রয়োজনীয়। যদি আপনি পুনরাবৃত্তির একমাত্র উপকারের জন্য প্যারামিটার থাকার ধারণাটি পছন্দ করেন না (আমি এই বিষয়টি গ্রহণ করি যে ব্যবহারকারী তাদের সাথে জগাখিচুড়ি করতে পারে) তবে Function#bindআংশিকভাবে প্রয়োগকৃত কার্যক্রমে সেগুলি লক করে রাখুন ।
কাস্টমকম্যান্ডার

@ কাস্টমকম্যান্ডার হ্যাঁ, আমি আমার উত্তরের প্রথম অংশে সংক্ষেপে এটি উল্লেখ করেছি - the traditional solution is to pass the count as a parameter। এটি বন্ধ হয়ে যাওয়া ভাষায় এটি একটি বিকল্প সমাধান। কিছু উপায়ে এটি অনুসরণ করা সহজ কারণ এটি সম্ভবত অসীম সংখ্যক চলক দৃষ্টান্তগুলির পরিবর্তে কেবল একটি পরিবর্তনশীল। অন্যান্য সমাধানে এই সমাধানটি জেনে রাখা যখন আপনি যে
জিনিসটিকে

counter--আপনার দাবিটি "দু'বার সঠিকভাবে বলা যায় না" সমাধান করার প্রথাগত উপায় হতে পারে
MonkeyZeus

1
পছন্দ করুন এছাড়াও, আপনি কীভাবে জানতে পারবেন যে কাউন্টারটি কীভাবে শুরু করতে হবে তা দেখার জন্য যে এটি আমরা খুঁজে পেতে চাইছি তা গণনা?
slebetman

22

আর একটি পদ্ধতি, যেহেতু আপনি সমস্ত সংখ্যা উত্পাদন করেন, তা হ'ল জেনারেটর ব্যবহার করা।

শেষ উপাদানটি হ'ল আপনার সংখ্যাটি nএকটি একক সংখ্যায় কমেছে এবং আপনি কতবার পুনরাবৃত্তি করেছেন তা গণনা করতে কেবল অ্যারের দৈর্ঘ্যটি পড়ুন।

const digits = [...to_single_digit(39)];
console.log(digits);
//=> [27, 14, 4]
<script>
function* to_single_digit(n) {
  do {
    n = [...String(n)].reduce((x, y) => x * y);
    yield n;
  } while (n > 9);
}
</script>


সর্বশেষ ভাবনা

আপনি আপনার ফাংশনে রিটার্ন-শুরুর শর্তটি বিবেচনা করতে চাইতে পারেন । এটি একটি শূন্য দিয়ে কোনো সংখ্যা হবে শূন্য ফিরে।

singleDigit(1024);       //=> 0
singleDigit(9876543210); //=> 0

// possible solution: String(n).includes('0')

1কেবলমাত্র তৈরি কোনও সংখ্যার ক্ষেত্রেও একই কথা বলা যেতে পারে ।

singleDigit(11);    //=> 1
singleDigit(111);   //=> 1
singleDigit(11111); //=> 1

// possible solution: [...String(n)].every(n => n === '1')

অবশেষে, আপনি কেবল ইতিবাচক পূর্ণসংখ্যা গ্রহণ করেন কিনা তা আপনি স্পষ্ট করেননি। আপনি যদি নেতিবাচক পূর্ণসংখ্যাকে গ্রহণ করেন তবে সেগুলিতে স্ট্রিংয়ে কাস্ট করা ঝুঁকিপূর্ণ হতে পারে:

[...String(39)].reduce((x, y) => x * y)
//=> 27

[...String(-39)].reduce((x, y) => x * y)
//=> NaN

সম্ভাব্য সমাধান:

const mult = n =>
  [...String(Math.abs(n))].reduce((x, y) => x * y, n < 0 ? -1 : 1)

mult(39)
//=> 27

mult(-39)
//=> -27

মহান। @ কাস্টমকম্ডার খুব স্পষ্টভাবে এটি ব্যাখ্যা করার জন্য আপনাকে ধন্যবাদ
chs242

6

এখানে অনেক আকর্ষণীয় উত্তর হয়েছে। আমি মনে করি আমার সংস্করণটি একটি অতিরিক্ত আকর্ষণীয় বিকল্প প্রস্তাব করে।

আপনি আপনার প্রয়োজনীয় ফাংশন দিয়ে বেশ কয়েকটি কাজ করেন। আপনি এটির পুনরাবৃত্তভাবে এক অঙ্কে হ্রাস করুন। আপনি মধ্যবর্তী মানগুলি লগ করুন এবং আপনি পুনরাবৃত্ত কলগুলির একটি গণনা চান। এই সমস্ত পরিচালনা করার একটি উপায় হ'ল খাঁটি ফাংশন লিখুন যা কোনও ডেটা স্ট্রাকচার ফিরিয়ে দেবে যাতে চূড়ান্ত ফলাফল থাকে, গৃহীত পদক্ষেপগুলি এবং কলগুলি একটিতে সমস্ত গণনা করে:

  {
    digit: 4,
    steps: [39, 27, 14, 4],
    calls: 3
  }

তারপরে আপনি চাইলে পদক্ষেপগুলি লগইন করতে পারেন, বা আরও প্রক্রিয়াজাতকরণের জন্য সেগুলি সঞ্চয় করতে পারেন।

এখানে এমন একটি সংস্করণ রয়েছে যা এটি করে:

const singleDigit = (n, steps = []) =>
  n <= 9
    ? {digit: n, steps: [... steps, n], calls: steps .length}
    : singleDigit ([... (n + '')] .reduce ((a, b) => a * b), [... steps, n])

console .log (singleDigit (39))

মনে রাখবেন যে আমরা ট্র্যাক করি stepsতবে এটির উদ্ভব করি calls। আমরা অতিরিক্ত প্যারামিটারের সাহায্যে কল গণনাটি ট্র্যাক করতে পারলাম বলে মনে হয় কিছুই লাভ হয়নি। আমরা পদক্ষেপটিও এড়িয়ে map(Number)চলেছি - গুণগুলি দ্বারা এগুলি যে কোনও ক্ষেত্রে সংখ্যায় জোর করা হবে।

সেই ডিফল্ট stepsপ্যারামিটারটি আপনার API এর অংশ হিসাবে উদ্ভাসিত হওয়ার বিষয়ে যদি আপনার উদ্বেগ থাকে তবে কোনও অভ্যন্তরীণ ফাংশন ব্যবহার করে এটি লুকানো যথেষ্ট সহজ:

const singleDigit = (n) => {
  const recur = (n, steps) => 
    n <= 9
      ? {digit: n, steps: [... steps, n], calls: steps .length}
      : recur ([... (n + '')] .reduce ((a, b) => a * b), [... steps, n])
  return recur (n, [])
}

এবং উভয় ক্ষেত্রেই কোনও সহায়ক কার্যে অঙ্কের গুণটি বের করা কিছুটা পরিষ্কার হতে পারে:

const digitProduct = (n) => [... (n + '')] .reduce ((a, b) => a * b)

const singleDigit = (n, steps = []) =>
  n <= 9
    ? {digit: n, steps: [... steps, n], calls: steps .length}
    : singleDigit (digitProduct(n), [... steps, n])

2
আরেকটি দুর্দান্ত উত্তর;) দয়া করে নোট করুন যে যখন এন নেতিবাচক digitProductহবে তখন ফিরে আসবে NaN( -39 ~> ('-' * '3') * '9')। সুতরাং আপনি n এর একটি নিখুঁত মান এবং ব্যবহার করতে -1বা 1আপনার হ্রাসের প্রাথমিক মান হিসাবে ব্যবহার করতে চাইতে পারেন ।
কাস্টমকম্যান্ডার

@customcommander: আসলে, এটা ফিরে আসবে {"digit":-39,"steps":[-39],"calls":0}সাল থেকে -39 < 9। যদিও আমি সম্মত হই যে এটি কিছু ত্রুটি-চেকিংয়ের সাথে করতে পারে: প্যারামিটারটি কোনও সংখ্যা? - এটা কি ধনাত্মক পূর্ণসংখ্যা? - ইত্যাদি আমি মনে করি না যে আমি এটি অন্তর্ভুক্ত করার জন্য আপডেট করব। এটি অ্যালগরিদম ক্যাপচার করে এবং ত্রুটি-হ্যান্ডলিং প্রায়শই কারও কোড-বেসের জন্য নির্দিষ্ট।
স্কট স্যয়েট

6

আপনি যদি কেবল এটি কয়বার হ্রাস পেয়েছে এবং নির্দিষ্টভাবে পুনরাবৃত্তির বিষয়ে যত্নশীল না হন তা গণনা করার চেষ্টা করছেন ... আপনি কেবল পুনরাবৃত্তি সরাতে পারেন। নীচের কোডটি মূল পোস্টের প্রতি বিশ্বস্ত থাকে কারণ এটি num <= 9হ্রাসের প্রয়োজন হিসাবে গণনা করা হয় না । অতএব, singleDigit(8)থাকবে count = 0, এবং singleDigit(39)থাকবে count = 3, শুধু ওপি এবং গ্রহণযোগ্য উত্তর প্রদর্শক মত:

const singleDigit = (num) => {
    let count = 0, ret, x;
    while (num > 9) {
        ret = 1;
        while (num > 9) {
            x = num % 10;
            num = (num - x) / 10;
            ret *= x;
        }
        num *= ret;
        count++;
        console.log(num);
    }
    console.log("Answer = " + num + ", count = " + count);
    return num;
}

9 বা তারও কম সংখ্যক প্রক্রিয়া করা (যেমন। num <= 9) অপ্রয়োজনীয় । দুর্ভাগ্যক্রমে ওপি কোডটি num <= 9এটি গণনা করে না এমনকী প্রক্রিয়া করবে। উপরের কোডটি মোটেও প্রক্রিয়া করবে না বা গণনা করবে না num <= 9। এটি কেবল এটি মাধ্যমে পাস।

আমি ব্যবহার না করা বেছে নিই .reduceকারণ প্রকৃত গণিতটি সম্পাদন করা খুব দ্রুত ছিল। এবং, আমার জন্য, বুঝতে সহজ।


গতিতে আরও চিন্তা

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

উভয় .map(Number)এবং console.log(প্রতিটি হ্রাস পদক্ষেপে) উভয়ই কার্যকর করা খুব দীর্ঘ এবং অপ্রয়োজনীয়। কেবল .map(Number)ওপি থেকে মুছে ফেলা প্রায় 4.38x এর গতি বাড়িয়ে তোলে। মুছে ফেলা console.logএতো তাড়াতাড়ি সঠিকভাবে পরীক্ষা করা প্রায় অসম্ভব (আমি এটির জন্য অপেক্ষা করতে চাইনি)।

সুতরাং, কাস্টমকম্যান্ডারের উত্তরের অনুরূপ , ব্যবহার .map(Number)না করে console.logএবং ফলাফলগুলিকে অ্যারে তে ঠেকানো এবং এর .lengthজন্য ব্যবহার countকরা অনেক দ্রুত। দুর্ভাগ্যবশত জন্য customcommander এর উত্তর, একটি ব্যবহার উত্পাদক ফাংশন সত্যিই সত্যিই ধীর (যে উত্তর 2.68x সম্পর্কে ছাড়া ওপি তুলনায় ধীর হয় .map(Number)এবং console.log)

এছাড়াও, ব্যবহার করার পরিবর্তে .reduceআমি কেবল আসল গণিত ব্যবহার করেছি। এই একক পরিবর্তনটি 3.59x এর একটি ফ্যাক্টর দ্বারা আমার ফাংশনটির সংস্করণ বাড়িয়েছে।

অবশেষে, পুনরাবৃত্তিটি ধীর হয়, এটি স্ট্যাকের জায়গা নেয়, আরও মেমরি ব্যবহার করে এবং এটি কতবার "পুনরাবৃত্তি" করতে পারে তার সীমাবদ্ধতা রয়েছে। বা, এক্ষেত্রে, হ্রাসের কতগুলি পদক্ষেপ এটি সম্পূর্ণ হ্রাস শেষ করতে ব্যবহার করতে পারে। আপনার পুনরাবৃত্তিকে পুনরাবৃত্তকারী লুপগুলিতে আবর্তিত করা সমস্ত কিছু স্ট্যাকের একই স্থানে রাখে এবং এটি শেষ করতে কতগুলি হ্রাস পদক্ষেপ ব্যবহার করতে পারে তার কোনও তাত্ত্বিক সীমা নেই। সুতরাং, এখানে এই ফাংশনগুলি প্রায় কোনও আকারের পূর্ণসংখ্যাকে "হ্রাস" করতে পারে, কেবলমাত্র মৃত্যুদন্ড কার্যকর করার সময় এবং একটি অ্যারে কত দীর্ঘ হতে পারে তা দ্বারা সীমাবদ্ধ।

এই সব মনে ...

const singleDigit2 = (num) => {
    let red, x, arr = [];
    do {
        red = 1;
        while (num > 9) {
            x = num % 10;
            num = (num - x) / 10;
            red *= x;
        }
        num *= red;
        arr.push(num);
    } while (num > 9);
    return arr;
}

let ans = singleDigit2(39);
console.log("singleDigit2(39) = [" + ans + "],  count = " + ans.length );
 // Output: singleDigit2(39) = [27,14,4],  count = 3

উপরের ফাংশনটি অত্যন্ত দ্রুত চলে। এটা খুলছেনা চেয়ে (ছাড়া দ্রুত 3.13x সম্পর্কে .map(Number)এবং console.logযতো তাড়াতাড়ি) এবং 8.4x সম্পর্কে customcommander এর উত্তর। মনে রাখবেন যে console.logওপি থেকে মুছে ফেলা এটিকে হ্রাসের প্রতিটি পদক্ষেপে একটি সংখ্যা উত্পাদন করতে বাধা দেয়। অতএব, প্রয়োজন এখানে অ্যারে এই ফলাফলগুলি ধাক্কা।

পিটি


1
এই উত্তরে শিক্ষার মান অনেক বেশি তাই তার জন্য ধন্যবাদ। I feel good code is also fast.আমি বলতে চাই যে কোড মানের হয়েছে প্রয়োজনীয়তা একটি পূর্বনির্ধারিত সেট বিরুদ্ধে পরিমাপ করা। পারফরম্যান্স যদি সেগুলির মধ্যে একটি না হয় তবে "দ্রুত" কোড দিয়ে যে কেউ বুঝতে পারে এমন কোড প্রতিস্থাপন করে আপনি কিছুই অর্জন করতে পারবেন না। আপনি যে পরিমাণ কোড দেখেছি তা বিশ্বাস করতে পারবেন না যে প্রতিবেদক হিসাবে যে বিন্দুতে অভিনয় করতে পেরেছি তা আর কেউ বুঝতে পারে না (কোনও কারণে অনুকূল কোডটিও বিনা শংসাপত্রযুক্ত থাকে;)। অবশেষে সচেতন হোন যে অলস-উত্পন্ন উত্সযুক্ত তালিকাগুলি একজনকে চাহিদা অনুযায়ী আইটেম গ্রহণ করতে দেয়।
কাস্টমকম্যান্ডার

আপনাকে ধন্যবাদ, আমি মনে করি। আইএমএইচও, কীভাবে করা যায় তার প্রকৃত গণিতটি পড়া আমার পক্ষে বোঝা সহজ ছিল .. আমি এখানে যে বেশিরভাগ উত্তরে দেখছি [...num+''].map(Number).reduce((x,y)=> {return x*y})বা এমনকি এমন [...String(num)].reduce((x,y)=>x*y)বক্তব্যের চেয়েও সহজ । সুতরাং, আমার কাছে, এটি প্রতিটি পুনরাবৃত্তিতে কী ঘটছে এবং আরও দ্রুততর তা আরও ভালভাবে বোঝার অতিরিক্ত সুবিধা পেয়েছিল । হ্যাঁ, মিনিফায়েড কোড (যার এটির স্থান রয়েছে) পড়তে ভয়ঙ্করভাবে শক্ত। তবে সেই ক্ষেত্রে একজন সচেতনভাবে তার পঠনযোগ্যতার বিষয়ে যত্নশীল নয় বরং কাটা-পেস্ট করে এগিয়ে যাওয়ার জন্য কেবল চূড়ান্ত ফলাফল।
পিম্প ট্রাইস্কিট

জাভাস্ক্রিপ্টের পূর্ণসংখ্যা বিভাগ নেই তাই আপনি সি এর সমতুল্য করতে পারেন digit = num%10; num /= 10;? num - xভাগ করার আগে ট্রেলিং ডিজিটটি সরিয়ে ফেলতে প্রথমে করণীয় সম্ভবত জেআইটি সংকলককে বাকী অংশটি পাওয়ার জন্য পৃথক বিভাগ করতে বাধ্য করবে।
পিটার কর্ডেস

আমার মনে হয় না se এগুলি হ'ল var( জেএসের কোনও intএস নেই)। অতএব, প্রয়োজনে একটি ফ্লোটে n /= 10;রূপান্তরিত nহবে। num = num/10 - x/10এটি একটি ফ্লোটে রূপান্তর করতে পারে যা সমীকরণের দীর্ঘ রূপ। সুতরাং, num = (num-x)/10;এটি একটি পূর্ণসংখ্যার জন্য আমাকে রিফ্যাক্টর সংস্করণটি ব্যবহার করতে হবে Java আমি জাভাস্ক্রিপ্টে খুঁজে পাবার মতো কোনও উপায় নেই যা আপনাকে একক বিভাগের ক্রিয়াকলাপের ভাগফল এবং বাকী উভয়ই দিতে পারে। এছাড়াও, digit = num%10; num /= 10;দুটি পৃথক বিবৃতি এবং এইভাবে দুটি পৃথক বিভাগ ক্রিয়াকলাপ। কিছুক্ষণ হয়েছে যখন আমি সি ব্যবহার করেছি, তবে আমি ভেবেছিলাম এটি সেখানেও সত্য।
পিম্প ট্রিজকিট

6

console.countআপনার ফাংশনে কেন কল করবেন না?

সম্পাদনা করুন: আপনার ব্রাউজারে চেষ্টা করার জন্য স্নিপেট:

function singleDigit(num) {
    console.count("singleDigit");

    let counter = 0
    let number = [...num + ''].map(Number).reduce((x, y) => {return x * y})

    if(number <= 9){
        console.log(number)
    }else{
        console.log(number)
        return singleDigit(number), counter += 1
    }
}
singleDigit(39)

আমি এটি ক্রোম 79 এবং ফায়ারফক্স 72 এ কাজ করছি


প্রতিবার ফাংশনটি ডাকা হওয়ার সাথে সাথে কাউন্টারটি রিসেট
কনসোল.কাউন্ট

2
আমি আপনার সমস্যাটি ক্রোম এবং ফায়ারফক্সে কাজ করার কারণে বুঝতে পারি না, আমি আমার উত্তরে একটি স্নিপেট যুক্ত করেছি
মিস্টারম্যাট

6

আপনি এই জন্য ক্লোজার ব্যবহার করতে পারেন।

কেবলমাত্র counterফাংশন বন্ধের মধ্যে সংরক্ষণ করুন।

এখানে উদাহরণ:

function singleDigitDecorator() {
	let counter = 0;

	return function singleDigitWork(num, isCalledRecursively) {

		// Reset if called with new params 
		if (!isCalledRecursively) {
			counter = 0;
		}

		counter++; // *

		console.log(`called ${counter} times`);

		let number = [...(num + "")].map(Number).reduce((x, y) => {
			return x * y;
		});

		if (number <= 9) {
			console.log(number);
		} else {
			console.log(number);

			return singleDigitWork(number, true);
		}
	};
}

const singleDigit = singleDigitDecorator();

singleDigit(39);

console.log('`===========`');

singleDigit(44);


1
তবে এইভাবে কাউন্টারটি পরবর্তী কলটিতে গণনা রাখে, প্রতিটি প্রাথমিক কলটিতে এটি পুনরায় সেট করা দরকার। এটি একটি কঠিন প্রশ্নের দিকে পরিচালিত করে: কীভাবে যখন বলতে হবে যে যখন কোনও পুনরাবৃত্ত ফাংশনকে অন্য প্রসঙ্গ থেকে ডাকা হয়, এক্ষেত্রে গ্লোবাল বনাম ফাংশন।
রবিজি

একটি চিন্তা সঙ্গে আসতে এই উদাহরণস্বরূপ। এটি ব্যবহারকারীকে তার প্রয়োজনের জন্য জিজ্ঞাসা করে সংশোধন করা যেতে পারে।
খোলিয়াভকো

@ রবজি আপনার প্রশ্নটি আমি বুঝতে পারি না। পুনরাবৃত্ত ফাংশনটি বন্ধের বাইরে কল করা যায় না কারণ এটি একটি অভ্যন্তরীণ ফাংশন। সুতরাং প্রসঙ্গটি পার্থক্য করার কোন সম্ভাবনা বা প্রয়োজন নেই কারণ কেবলমাত্র একটি সম্ভাব্য প্রসঙ্গ রয়েছে
স্লেব্যাটম্যান

@ স্লেবেটম্যান কাউন্টারটি কখনই রিসেট হয় না। ফিরিয়ে দেওয়া ফাংশন singleDigitDecorator()যতবার ডাকে ততবার একই কাউন্টারকে বাড়িয়ে তুলবে।
কাস্টমমন্ডার

1
@ slebetman — সমস্যাটি হ'ল সিঙ্গলডিজিটডেকোরেটর ফিরিয়ে ফাংশনটি আবার কল করার পরে তার কাউন্টারটি পুনরায় সেট করে না। এটি সেই ফাংশন যা কাউন্টারটি পুনরায় সেট করতে হবে তা জানতে হবে, অন্যথায় প্রতিটি ব্যবহারের জন্য ফাংশনের একটি নতুন উদাহরণ প্রয়োজন। Function.caller এর জন্য একটি সম্ভাব্য ব্যবহারের কেস ? ;-)
রবজি

1

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

from functools import reduce

def single_digit(n: int) -> tuple:
    """Take an integer >= 0 and return a tuple of the single-digit product reduction
    and the number of reductions performed."""

    def _single_digit(n, i):
        if n <= 9:
            return n, i
        else:
            digits = (int(d) for d in str(n))
            product = reduce(lambda x, y: x * y, digits)
            return _single_digit(product, i + 1)

    return _single_digit(n, 0)

>>> single_digit(39)
(4, 3)

1
পাইথনে আমি এই জাতীয় কিছু পছন্দ করতাম ।
phipsgabler
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.