আন্ডারহ্যান্ডড কোড প্রতিযোগিতা: তাত্ক্ষণিকভাবে সাজানো নয় [বন্ধ]


28

কাজটি

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

import sys

for line in sorted(sys.stdin):
    print(line.rstrip('\n'))

আন্ডারহ্যান্ডড অংশ

ওএস ওয়ারের অনুরূপ , আপনার লক্ষ্যটি প্রতিযোগিতামূলক প্ল্যাটফর্মে আপনার প্রোগ্রামটি ইচ্ছাকৃতভাবে আরও ধীরে ধীরে চালিয়ে দেওয়ার মাধ্যমে প্রমাণ করা যায় যে আপনার অনুকূল প্ল্যাটফর্মটি "আরও ভাল"। এই প্রতিযোগিতার স্বার্থে, একটি "প্ল্যাটফর্ম" এর যে কোনও সমন্বয় নিয়ে গঠিত:

  • প্রসেসর
    • আর্কিটেকচার (x86, আলফা, এআরএম, এমআইপিএস, পাওয়ারপিসি, ইত্যাদি)
    • সাক্ষ্যদান (64-বিট বনাম 32-বিট বনাম 16-বিট)
    • বড়- বনাম লিটল এন্ডিয়ান
  • অপারেটিং সিস্টেম
    • উইন্ডোজ বনাম লিনাক্স বনাম ম্যাক ওএস ইত্যাদি
    • একই অপারেটিং সিস্টেমের বিভিন্ন সংস্করণ
  • ভাষা বাস্তবায়ন
    • বিভিন্ন সংকলক / দোভাষী বিক্রেতারা (যেমন, এমএসভিসি ++ বনাম জিসিসি)
    • একই সংকলক / দোভাষীর বিভিন্ন সংস্করণ

যদিও আপনি কোড লিখে যেমন প্রয়োজনীয়তা পূরণ করতে পারে:

#ifndef _WIN32
    Sleep(1000);
#endif

এ জাতীয় উত্তর উঁচু করা উচিত নয়। লক্ষ্য সূক্ষ্ম হতে হয়। আদর্শভাবে, আপনার কোড করা উচিত চেহারা এটা প্ল্যাটফর্ম-নির্ভরশীল এ সব না পারে। আপনি যদি না কোন #ifdef(চালু ভিত্তিক বা অবস্থার বিবৃতি os.nameবা System.Environment.OSVersionবা যাই হোক না কেন), তারা একটি বিশ্বাসযোগ্য আত্মপক্ষ সমর্থন (অবশ্যই মিথ্যা, উপর ভিত্তি করে) থাকা উচিত।

আপনার উত্তরে অন্তর্ভুক্ত করুন

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

4
এটি আমার ধারণা থেকে শক্ত than আমি যে উত্তরগুলি নিয়ে আসতে পারি তা হ'ল হয় খুব দীর্ঘ এবং কিছুটা সুস্পষ্ট, বা খুব সংক্ষিপ্ত এবং অত্যন্ত সুস্পষ্ট :-(
চিকিত্সা অসম্পূর্ণ

2
আমি এই প্রশ্নটিকে অফ-টপিক হিসাবে বন্ধ করতে ভোট দিচ্ছি কারণ ছদ্মবেশী চ্যালেঞ্জগুলি এখন আর এই সাইটে অন টপিক নয়। meta.codegolf.stackexchange.com/a/8326/20469
বিড়াল

উত্তর:


29

সি

CleverSort

ক্লিভারসোর্টটি একটি স্টেট অফ দ্য আর্ট (অর্থাত্ ইঞ্জিনিয়ারড এবং সাব-অনুকূল) দ্বি-ধাপের স্ট্রিং বাছাই অ্যালগরিদম।

পদক্ষেপ 1 এ, এটি Radix বাছাই এবং প্রতিটি লাইনের প্রথম দুটি বাইট ব্যবহার করে ইনপুট লাইনগুলিকে প্রাক-বাছাই করে শুরু হয় । রেডিক্স সাজানটি তুলনামূলক নয় এবং স্ট্রিংয়ের জন্য খুব ভাল কাজ করে।

পদক্ষেপ 2 এ, এটি স্ট্রিংগুলির প্রাক-সাজানো তালিকায় সন্নিবেশ সাজানোর ব্যবহার করে। যেহেতু তালিকাটি প্রথম ধাপ 1 এর পরে প্রায় বাছাই করা হয়েছে, সন্নিবেশ সাজানোর কাজটি এই কাজের জন্য বেশ কার্যকর।

কোড

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Convert first two bytes of Nth line into integer

#define FIRSTSHORT(N) *((uint16_t *) input[N])

int main()
{
    char **input = 0, **output, *ptemp;
    int first_index[65536], i, j, lines = 0, occurrences[65536];
    size_t temp;

    // Read lines from STDIN

    while(1)
    {
        if(lines % 1000 == 0)
            input = realloc(input, 1000 * (lines / 1000 + 1) * sizeof(char*));

        if(getline(&input[lines], &temp, stdin) != -1)
            lines++;
        else
            break;
    }

    output = malloc(lines * sizeof(char*));

    // Radix sort

    memset(occurrences, 0, 65536 * sizeof(int));

    for(i = 0; i < lines; i++) occurrences[FIRSTSHORT(i)]++;

    first_index[0] = 0;

    for(i = 0; i < 65536 - 1; i++)
        first_index[i + 1] = first_index[i] + occurrences[i];

    memset(occurrences, 0, 65536 * sizeof(int));

    for(i = 0; i < lines; i++)
    {
        temp = FIRSTSHORT(i), output[first_index[temp] + occurrences[temp]++] = input[i];
    }

    // Insertion sort

    for(i = 1; i < lines; i++)
    {
        j = i;

        while(j > 0 && strcmp(output[j - 1], output[j]) > 0)
            ptemp = output[j - 1], output[j - 1] = output[j], output[j] = ptemp, j--;
    }

    // Write sorted lines to STDOUT

    for(i = 0; i < lines; i++)
        printf("%s", output[i]);
}

প্ল্যাটফর্ম

আমরা সবাই জানি যে বিগ-এন্ডিয়ান মেশিনগুলি তাদের ছোট-এন্ডিয়ান অংশগুলির তুলনায় অনেক বেশি দক্ষ। বেঞ্চমার্কিংয়ের জন্য, আমরা ক্রেভারসোর্টটি অপটিমাইজেশন চালু করে সংকলন করব এবং এলোমেলোভাবে 4-বাইট লাইনের একটি বিশাল তালিকা (মাত্র 100,000 স্ট্রিং) তৈরি করব:

$ gcc -o cleversort -Ofast cleversort.c
$ head -c 300000 /dev/zero | openssl enc -aes-256-cbc -k '' | base64 -w 4 > input
$ wc -l input
100011 input

বিগ-এন্ডিয়ান মানদণ্ড

$ time ./cleversort < input > /dev/null

real    0m0.185s
user    0m0.181s
sys     0m0.003s

খুব বাজে না.

লিটল-এডিয়ান বেচমার্ক

$ time ./cleversort < input > /dev/null

real    0m27.598s
user    0m27.559s
sys     0m0.003s

বু, ছোট এন্ডিয়ান! ছি!

বিবরণ

সন্নিবেশ সাজানো প্রায় সাজানো তালিকার জন্য সত্যিই দক্ষ, তবে এলোমেলোভাবে বাছাই করাগুলির জন্য এটি মারাত্মকভাবে অক্ষম।

ক্লেভারসোর্টের আন্ডারহ্যান্ড অংশটি প্রথম ম্যাক্রো:

#define FIRSTSHORT(N) *((uint16_t *) input[N])

বিগ-এন্ডিয়ান মেশিনে, ডিকোসোগ্রাফিকভাবে দুটি 8-বিট পূর্ণসংখ্যার একটি স্ট্রিং অর্ডার করে বা তাদের 16-বিট পূর্ণসংখ্যায় রূপান্তর করে এবং তারপরে ক্রম দিয়ে একই ফলাফল দেয়।

স্বাভাবিকভাবেই, লিটল-এন্ডিয়ান মেশিনগুলিতেও এটি সম্ভব, তবে ম্যাক্রো হওয়া উচিত ছিল

#define FIRSTSHORT(N) (input[N][0] | (input[N][1] >> 8))

যা সমস্ত প্ল্যাটফর্মে প্রত্যাশার মতো কাজ করে।

উপরের "বিগ-এন্ডিয়ান বেঞ্চমার্ক" আসলে সঠিক ম্যাক্রো ব্যবহারের ফলাফল।

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


16

পাইথন 2 বনাম পাইথন 3

স্পষ্টতই, পাইথন 3 পাইথন 2 এর চেয়ে দ্রুতগতির কয়েকটি অর্ডার orders আসুন উদাহরণস্বরূপ শেলসোর্ট অ্যালগরিদমের এই বাস্তবায়নটি নেওয়া যাক :

কোড

import sys
from math import log

def shellsort(lst):

    ciura_sequence = [1, 4, 10, 23, 57, 132, 301, 701]  # best known gap sequence (Ciura, 2001)

    # check if we have to extend the sequence using the formula h_k = int(2.25h_k-1)
    max_sequence_element = 1/2*len(lst)
    if ciura_sequence[-1] <= max_sequence_element:
        n_additional_elements = int((log(max_sequence_element)-log(701)) / log(2.25))
        ciura_sequence += [int(701*2.25**k) for k in range(1,n_additional_elements+1)]
    else:
        # shorten the sequence if necessary
        while ciura_sequence[-1] >= max_sequence_element and len(ciura_sequence)>1:
            ciura_sequence.pop()

    # reverse the sequence so we start sorting using the largest gap
    ciura_sequence.reverse()

    # shellsort from http://sortvis.org/algorithms/shellsort.html
    for h in ciura_sequence:
        for j in range(h, len(lst)):
            i = j - h
            r = lst[j]
            flag = 0
            while i > -1:
                if r < lst[i]:
                    flag = 1
                    lst[i+h], lst[i] = lst[i], lst[i+h]
                    i -= h
                else:
                    break
            lst[i+h] = r

    return lst

# read from stdin, sort and print
input_list = [line.strip() for line in sys.stdin]
for line in shellsort(input_list):
    print(line)

assert(input_list==sorted(input_list))

উচ্চতার চিহ্ন

একটি পরীক্ষার ইনপুট প্রস্তুত করুন। এটি ডেনিস উত্তর থেকে নেওয়া হয়েছে তবে কম শব্দে - পাইথন 2 হ'ল খুব ধীর ...

$ head -c 100000 /dev/zero | openssl enc -aes-256-cbc -k '' | base64 -w 4 > input

পাইথন 2

$ time python2 underhanded2.py < input > /dev/null 

real    1m55.267s
user    1m55.020s
sys     0m0.284s

পাইথন ঘ

$ time python3 underhanded2.py < input > /dev/null 

real    0m0.426s
user    0m0.420s
sys     0m0.006s

আন্ডারহ্যান্ড কোডটি কোথায়?

আমি ধরে নিয়েছি কিছু পাঠক নিজেই চালকের শিকার করতে চান, তাই আমি উত্তরটি কোনও স্পয়লার ট্যাগ দিয়ে আড়াল করি।

কৌশলটি হ'ল গণনাতে পূর্ণসংখ্যা বিভাগ max_sequence_element। পাইথনে 2 1/2শূন্যে মূল্যায়ন করে এবং তাই প্রকাশটি সর্বদা শূন্য। যাইহোক, অপারেটরের আচরণটি পাইথন 3 এর ফ্লোটিং পয়েন্ট বিভাগে পরিবর্তিত হয়েছে কারণ এই পরিবর্তনশীল ফাঁক অনুক্রমের দৈর্ঘ্যকে নিয়ন্ত্রণ করে, যা শেলসোর্টের একটি সমালোচনামূলক পরামিতি, পাইথন 2 একটি সিকোয়েন্স ব্যবহার করে শেষ হয় যেখানে পাইথন যখন এক নম্বর থাকে তবে পাইথন 2 3 সঠিক ক্রম ব্যবহার করে। এটি পাইথন 2 এর জন্য এক চতুর্থাংশ রান সময়তে ফলাফল করে।

বোনাস 1:

আপনি গণনার মধ্যে 1বা এর পরে বিন্দু যুক্ত করে কোডটি ঠিক করতে পারেন 2

বোনাস 2:

কমপক্ষে আমার মেশিনে পাইথন 2 স্থির কোডটি চালানোর সময় পাইথন 3 এর চেয়ে কিছুটা দ্রুত ...


ভালো খেলেছ! নিতপিক্স সময়: flagকেবল লেখার জন্য দেখায়, আপনি কি এটি সরাতে পারবেন না? এছাড়াও, rযদি আপনি এটি অতিরিক্ত ব্যবহার করেন if lst[i+h] < lst[i]: ...। অন্যদিকে, আপনি যদি rঅদলবদল রাখেন? তুমি কি করতে পার না lst[i+h] = lst[i]? এই সব কি ইচ্ছাকৃত বিভ্রান্তি?
জোনাস কলকার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.