আইটেমগুলি পুনরায় অর্ডার করার সময় সাজানোর কী তৈরি করা হয়


11

আমাদের কাছে প্রচুর আইটেম রয়েছে যা শেষ ব্যবহারকারী পছন্দসই অর্ডারে সংগঠিত করতে সক্ষম হবে। আইটেমগুলির সেটটি অর্ডারযুক্ত নয়, তবে প্রতিটি আইটেমে একটি সাজানোর কী রয়েছে যা পরিবর্তিত হতে পারে।

আমরা একটি অ্যালগরিদম সন্ধান করছি যা যুক্ত হওয়া বা সরানো আইটেমের জন্য একটি নতুন সাজানোর কী তৈরি করার অনুমতি দেবে যা হয় হয় প্রথম আইটেম, শেষ আইটেম বা কোনও দুটি আইটেমের মধ্যে। আমরা প্রত্যাশা করছি যে কেবল স্থানান্তরিত হচ্ছে আইটেমের সাজানোর কীটি সংশোধন করতে হবে।

একটি উদাহরণ অ্যালগরিদম হ'ল প্রতিটি সাজানোর কীটি একটি ভাসমান পয়েন্ট সংখ্যা হবে এবং দুটি আইটেমের মধ্যে কোনও আইটেম রাখার সময় বাছাই কীটি তাদের গড় হিসাবে সেট করুন। প্রথম বা শেষ পর্যন্ত কোনও আইটেম স্থাপন করা বাহ্যতম মান + - 1 নেবে।

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

এর জন্য কি কোনও উপযুক্ত অ্যালগরিদম কাজ করবে উদাহরণস্বরূপ, স্ট্রিংগুলি ব্যবহার করে, যা এই ত্রুটিগুলি দ্বারা প্রভাবিত হবে না?

আমরা বিপুল সংখ্যক পদক্ষেপকে সমর্থন করতে চাইছি না, তবে উপরে বর্ণিত অ্যালগরিদম প্রায় 50 টি পদক্ষেপের পরে ডাবল-নির্ভুলতা ভাসমান পয়েন্ট সংখ্যাতে ব্যর্থ হতে পারে।


স্ট্রিংগুলি একটি সুস্পষ্ট পছন্দ, কারণ আপনি কেবল দ্বিখণ্ডিত করার জন্য তাদের শেষেরগুলিতে অক্ষর যুক্ত রাখতে পারেন। এটি বলেছিল, আমি মনে করি এটির কাছে যাওয়ার আরও ভাল উপায় আছে।
রবার্ট হার্ভে

আমার মাথার শীর্ষ থেকে আমি দেখতে পাচ্ছি না যে এটি অন্য আইটেমগুলির কীগুলি সংশোধন না করে স্ট্রিংগুলি ব্যবহার করে কীভাবে কাজ করবে।
সাম্পো

3
আপনি যে সমস্যার বর্ণনা দিচ্ছেন তাকে অর্ডার রক্ষণাবেক্ষণের সমস্যা
নাথান মেরিল

1
তালিকার অন্যান্য আইটেমগুলি সংশোধন না করার বিষয়ে আপনি কেন উদ্বিগ্ন?
জিইআর

1
আপনি এটি স্ট্রিং দিয়ে কীভাবে কাজ করবেন তা এইরকম: A, B, C- A, AA, B, C- A, AA, AB, B, C- A, AA, AAA, AAB, AAC, AB, AC, B, C। অবশ্যই, আপনি সম্ভবত আপনার অক্ষরগুলি আরও ফাঁকা রাখতে চাইবেন যাতে স্ট্রিংগুলি এত তাড়াতাড়ি বৃদ্ধি না পায় তবে এটি করা যায়।
রবার্ট হার্ভে

উত্তর:


4

সমস্ত মন্তব্য এবং উত্তরের সংক্ষিপ্তসার হিসাবে:

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

দুটি সমস্যাযুক্ত ক্রিয়াকলাপটি শুরুতে / শেষে বারবার আইটেমগুলি সন্নিবেশ করানো হয় এবং বারবার একই স্থানে আইটেমগুলি সন্নিবেশ করা বা সরানো হয় (উদাহরণস্বরূপ তিনটি উপাদান বারবার প্রথম দু'জনের মধ্যে তৃতীয় উপাদানটি সরিয়ে নিয়ে যায়, বা বারবার দ্বিতীয় হিসাবে নতুন উপাদান যুক্ত করে উপাদান)।

একটি তাত্ত্বিক দৃষ্টিকোণ থেকে (অর্থাত্‍ অসীম পুনঃনির্মাণের অনুমতি দেওয়া) একমাত্র সমাধান আমি দুটি সীমাহীন আকারের পূর্ণসংখ্যাকে a / b হিসাবে ভগ্নাংশ হিসাবে ব্যবহার করতে পারি। এটি মধ্য-সন্নিবেশকারীদের জন্য অসীম নির্ভুলতার অনুমতি দেয় তবে সংখ্যাটি ক্রমশ বড় হতে পারে।

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

পূর্ণসংখ্যার জন্য বাছাই করা কীগুলির জন্য প্রাথমিক স্পেসিং চয়ন করা দরকার যা আপনি কত মিড-ইনসার্টগুলি সম্পাদন করতে পারবেন তা সীমাবদ্ধ করে। আপনি যদি প্রাথমিকভাবে 1024 কী আলাদা করে রাখেন তবে আপনার সংলগ্ন সংখ্যা থাকার আগে আপনি কেবলমাত্র 10 টি সবচেয়ে খারাপ ক্ষেত্রে মিড-সন্নিবেশগুলি সম্পাদন করতে পারেন। বৃহত্তর প্রাথমিক স্পেসিং নির্বাচন করা কতগুলি প্রথম / শেষ সন্নিবেশ সম্পাদন করতে পারে তা সীমাবদ্ধ করে। একটি 64-বিট পূর্ণসংখ্যার ব্যবহার করে, আপনি যে কোনও উপায়েই ~ 63 ক্রিয়াকলাপের মধ্যে সীমাবদ্ধ which

ভাসমান পয়েন্টের মানগুলি ব্যবহার করে কোনও পূর্ববর্তী ব্যবধান নির্বাচন করার প্রয়োজনীয়তা সরিয়ে ফেলা হয়। অ্যালগরিদম সহজ:

  1. Elementোকানো প্রথম উপাদানটির একটি সাজানোর কী 0.0 রয়েছে
  2. প্রথম বা শেষের মধ্যে একটি উপাদান orোকানো (বা সরানো) এর মধ্যে প্রথম এলিমেন্টের ক্রম কী রয়েছে - যথাক্রমে 1.0 বা শেষ উপাদান + 1.0।
  3. দুটি উপাদানের মধ্যে একটি উপাদান (োকানো (বা সরানো) দুটির গড়ের সমান বাছাই কী রয়েছে।

একটি ডাবল-নির্ভুলতা ফ্লোট ব্যবহার 52 টি সবচেয়ে খারাপ ক্ষেত্রে মিড-সন্নিবেশ এবং কার্যকরভাবে অসীম (প্রায় 1e15) প্রথম / শেষ সন্নিবেশকে অনুমতি দেয়। অনুশীলনে যখন অ্যালগরিদমের চারপাশে আইটেমগুলি সরিয়ে ফেলা হয় তখন সেগুলি নিজেকেই সংশোধন করে,

ডাবল-স্পষ্টতা ভাসমানগুলিরও সুবিধা রয়েছে যে তারা সমস্ত প্ল্যাটফর্ম দ্বারা সমর্থিত এবং ব্যবহারিকভাবে সমস্ত পরিবহন বিন্যাস এবং লাইব্রেরি দ্বারা সহজেই সঞ্চিত এবং পরিবহন করা হয়। এটিই আমরা ব্যবহার করে শেষ করেছি।


1

আমি @ সাম্পোর সারাংশের ভিত্তিতে টাইপস্ক্রিপ্টে একটি সমাধান লিখেছি। কোডটি নীচে পাওয়া যাবে।

পথে বেশ কয়েকটি অন্তর্দৃষ্টি পেল।

  • শুধু মাঝখানে সন্নিবেশ দুই বিদ্যমান সাজানোর কী মধ্যে (অর্থাত সাজানোর) একটি নতুন সাজানোর কী জেনারেট করতে, সোয়াপিং করে প্রয়োজন না টুকরা (অর্থাত নতুন midpoints) কারণ। আপনি যদি দুটি আইটেম সরান এবং আপনি কেবল তার একটিটির স্পর্শ করেছেন তবে তালিকার দুটি উপাদান কী কী অবস্থান পরিবর্তন করেছে সে সম্পর্কে আপনি তথ্য হারাচ্ছেন। এমনকি যদি এটি শুরু করার প্রয়োজন ছিল তবে নিশ্চিত হয়ে নিন যে এটি একটি ভাল ধারণা

  • প্রতি 1074: ম মিডপয়েন্ট বিভক্ত হয়ে আমাদের ভাসমান পয়েন্টের পরিসীমা স্বাভাবিক করতে হবে। আমরা নতুন মিডপয়েন্টটি আক্রমণকারীটিকে সন্তুষ্ট করে কিনা তা খতিয়ে পরীক্ষা করে এটি সনাক্ত করি

    a.sortKey < m && m < b.sortKey

  • স্কেলিং কোনও বিষয় নয়, বাছাই কীগুলি যেমন স্বাভাবিক করা হয় তখনও প্রতিটি 1074মিডপয়েন্ট বিভাজনে স্বাভাবিকীকরণ ঘটে । যদি আমরা সংখ্যাগুলি আরও বেশিভাবে শুরু করতে বিতরণ করি তবে পরিস্থিতির উন্নতি হবে না।

  • কী অনুসারে বাছাই করুন অবিশ্বাস্যর বিরল। আপনি এই ব্যয়টিকে এমন বিন্দুতে পরিণত করবেন যেখানে সাধারণীকরণ লক্ষণীয় নয়। যদিও, আপনার কাছে উপাদানগুলির সংখ্যা বেশি থাকলে আমি এই পদ্ধতির সাথে সাবধানতা অবলম্বন করব।


export interface HasSortKey {
  sortKey: number;
}

function normalizeList<T extends HasSortKey>(list: Array<T>) {
  const normalized = new Array<T>(list.length);
  for (let i = 0; i < list.length; i++) {
    normalized[i] = { ...list[i], sortKey: i };
  }
  return normalized;
}

function insertItem<T extends HasSortKey>(
  list: Array<T>,
  index: number,
  item: Partial<T>
): Array<T> {
  if (list.length === 0) {
    list.push({ ...item, sortKey: 0 } as T);
  } else {
    // list is non-empty

    if (index === 0) {
      list.splice(0, 0, { ...item, sortKey: list[0].sortKey - 1 } as T);
    } else if (index < list.length) {
      // midpoint, index is non-zero and less than length

      const a = list[index - 1];
      const b = list[index];

      const m = (a.sortKey + b.sortKey) / 2;

      if (!(a.sortKey < m && m < b.sortKey)) {
        return insertItem(normalizeList(list), index, item);
      }

      list.splice(index, 0, { ...item, sortKey: m } as T);
    } else if (index === list.length) {
      list.push({ ...item, sortKey: list[list.length - 1].sortKey + 1 } as T);
    }
  }
  return list;
}

export function main() {
  const normalized: Array<number> = [];

  let list: Array<{ n: number } & HasSortKey> = [];

  list = insertItem(list, 0, { n: 0 });

  for (let n = 1; n < 10 * 1000; n++) {
    const list2 = insertItem(list, 1, { n });
    if (list2 !== list) {
      normalized.push(n);
    }
    list = list2;
  }

  let m = normalized[0];

  console.log(
    normalized.slice(1).map(n => {
      const k = n - m;
      m = n;
      return k;
    })
  );
}

0

সেখানে হয়ে গেছেন, হয়ে গেছে, আবার এটি করতে হতে পারে। সাজানোর কী হিসাবে একটি স্ট্রিং ব্যবহার করুন, তারপরে আপনি সর্বদা দুটি প্রদত্ত কীগুলির মধ্যে থাকা একটি কী খুঁজে পাবেন। স্ট্রিংগুলি যদি আপনার স্বাদের জন্য খুব দীর্ঘ হয় তবে আপনাকে একাধিক বা সমস্ত বাছাই কীগুলি সংশোধন করতে হবে।


1
যদিও আপনি অন্য স্ট্রিং কী এর আগে থাকা কীটি সর্বদা খুঁজে পেতে পারেন না।
সাম্পো

-1

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


2
এটি আসলে ভাসা ব্যবহারের চেয়ে খারাপ। প্রাথমিক পর্যায়ে 500 এর ব্যবধান কেবল 8-9 মিডপয়েন্ট সন্নিবেশকে (2 ^ 9 = 512) অনুমতি দেয়, যখন একটি ডাবল ফ্লোট প্রায় 50টিকে অনুমতি দেয়, প্রাথমিকভাবে কোনও ফাঁক বাছাইয়ের কোনও সমস্যা নেই issue
সাম্পো

500 ব্যবধান এবং ভাসমান ব্যবহার করুন !
রব মুলদার

মাঝারি সন্নিবেশের জন্য সীমাবদ্ধ ফ্যাক্টরটি হ'ল তাত্পর্যপূর্ণ বিটের সংখ্যা হওয়ায় একটি ভাসা ব্যবহার করার সময় ব্যবধানটি কোনও পার্থক্য করে না। এই কারণেই আমি ফ্লোটগুলি ব্যবহার করার সময় 1.0 এর ডিফল্ট ফাঁক প্রস্তাব করি।
সাম্পো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.