দ্রুত লাইন অঙ্কন অ্যালগরিদম


9

কাজটি হ'ল 16 বিট পূর্ণসংখ্যার অ্যারেতে অনুভূমিক রেখা আঁকার কোনও উপায় খুঁজে পাওয়া।

আমরা প্রতি শব্দ 16 পিক্সেল সহ 256x192 পিক্সেল অ্যারে ধরে নিচ্ছি। একটি লাইন সেট (1) বিটের একটি সংযুক্ত রান। লাইনগুলি কোনও শব্দের মাঝামাঝি থেকে শুরু করতে পারে, অন্য কোনও শব্দকে ওভারল্যাপ করতে পারে এবং কোনও শব্দের মধ্যে শেষ হতে পারে; তারা একই শব্দ শুরু এবং শেষ হতে পারে। তারা পরবর্তী লাইনে আবদ্ধ নাও হতে পারে। ইঙ্গিত: মাঝারি শব্দগুলি সহজ - কেবল 0xffff লিখুন, তবে প্রান্তগুলি জটিল হবে, যেমন একই শব্দের শুরু এবং শেষের ক্ষেত্রে কেস পরিচালনা করবে। একটি ফাংশন / পদ্ধতি / রুটিন অবশ্যই অনুভূমিক প্রারম্ভ এবং স্টপ পয়েন্টগুলি, পাশাপাশি অ্যায় স্থানাঙ্ক নির্দেশ করে একটি এক্স 0 এবং এক্স 1 স্থানাঙ্ক গ্রহণ করতে হবে।

আমি এগুলি থেকে নিজেকে বাদ দিই কেননা আমি এমবেডেড প্রসেসরের জন্য নিজেকে প্রায় অভিন্ন অ্যালগরিদম ডিজাইন করেছি তবে আমি আগ্রহী যে অন্যেরা এটি সম্পর্কে কীভাবে যেতে পারে। তুলনামূলকভাবে দ্রুত অপারেশনগুলি ব্যবহারের জন্য বোনাস পয়েন্টগুলি (উদাহরণস্বরূপ, একটি এম্বেডড মেশিনে একটি bit৪ বিট গুণ বা ফ্লোটিং পয়েন্ট অপারেশন দ্রুত হবে না তবে একটি সাধারণ বিট শিফট হবে))


2
কোডগল্ফ শর্ট কোড সম্পর্কে, দ্রুত কোড বা গতির জন্য অনুকূলকরণ নয়।
হলভাবো

@ হাল্ভাবো আমার সমাধানটি বেশ সংক্ষিপ্ত, প্রায় 5 টি লাইন যখন সীমা পরীক্ষা করা এবং অতিরিক্ত বৈশিষ্ট্যগুলি (পিক্সেলগুলিকে সেট করার পরিবর্তে টগল করার মতো) সরিয়ে ফেলা হয়।
থমাস ও

9
@ হ্যালভাবো, এই সাইটটি কেবল কোডগল্ফ নয়। গতির জন্য অনুকূলকরণ সম্পর্কেও, তবে সমস্ত ধরণের অনুকূলিতকরণ নয়: হার্ডওয়্যার বিশদ নয়, তবে অ্যালগরিদমের জটিলতা।
নাকিলন

@ নকিলন: আমি একমত নই তাহলে এই সাইটটির নাম কোড গল্ফ কেন রাখা হয়েছে? অ্যালগরিদমিক জটিলতা এবং গতি অপ্টিমাইজেশান আলোচনার জন্য হাজার হাজার অন্যান্য সাইট রয়েছে।
হলভাবো

5
@ হালভাবাবো: এফএকিউ থেকে - "কোড গল্ফ - স্ট্যাক এক্সচেঞ্জ কোড গল্ফারদের জন্য এবং কোড গল্ফিংয়ে আগ্রহী (প্রাথমিক থেকে বিশেষজ্ঞগণ) এবং প্রোগ্রামিং ধাঁধাতে আগ্রহী তাদের জন্য।" আমি এটি একটি প্রোগ্রামিং ধাঁধা বিবেচনা করি।
থমাস হে

উত্তর:


3

এই কোডটি ধরে নিয়েছে যে x0 এবং x1 উভয়ই অন্তর্ভুক্তিক শেষ বিন্দু, এবং সেই শব্দগুলি সামান্য এন্ডিয়ান (অর্থাত্ (0,0) পিক্সেল সেট করা যেতে পারে array[0][0]|=1)।

int line(word *array, int x0, int x1, int y) {
  word *line = array + (y << 4);
  word *start = line + (x0 >> 4);
  word *end = line + (x1 >> 4);
  word start_mask = (word)-1 << (x0 & 15);
  word end_mask = (unsigned word)-1 >> (15 - (x1 & 15));
  if (start == end) {
    *start |= start_mask & end_mask;
  } else {
    *start |= start_mask;
    *end |= end_mask;
    for (word *p = start + 1; p < end; p++) *p = (word)-1;
  }
}

1
এটা কত দ্রুত?
ব্যবহারকারী অজানা

1

পাইথন

এখানে প্রধান কৌশলটি পিক্সেলের বিটমাস্কগুলি সঞ্চয় করতে একটি সারণী ব্যবহার করা। এটি কয়েকটি অপারেশন সংরক্ষণ করে। একটি এমবিবিড প্ল্যাটফর্মের জন্য একটি আজকাল এম্বেড প্ল্যাটফর্মের জন্যও 1 কেবি টেবিল এত বড় নয়

স্থানটি যদি সত্যিই শক্ত হয় তবে কয়েক দফার জন্য & 0xf এর জন্য অনুসন্ধানের টেবিলটি কেবল 64৪ বিতে কমানো যেতে পারে

এই কোডটি পাইথনে রয়েছে, তবে বিট ক্রিয়াকলাপ সমর্থন করে এমন কোনও ভাষায় পোর্ট করা সহজ।

যদি সি ব্যবহার করে switchথাকে তবে আপনি ডাফের ডিভাইসটি ব্যবহার করে লুপটি আনওয়াইন্ডিং বিবেচনা করতে পারেন । যেহেতু লাইনটি সর্বোচ্চ 16 শব্দের প্রশস্ত, তাই আমি switch14 টি লাইন প্রসারিত করব এবং whileসম্পূর্ণরূপে বিতরণ করব ।

T=[65535, 32767, 16383, 8191, 4095, 2047, 1023, 511,
   255, 127, 63, 31, 15, 7, 3, 1]*16
U=[32768, 49152, 57344, 61440, 63488, 64512, 65024, 65280,
   65408, 65472, 65504, 65520, 65528, 65532, 65534, 65535]*16

def drawline(x1,x2,y):
    y_=y<<4
    x1_=y_+(x1>>4)
    x2_=y_+(x2>>4)
    if x1_==x2_:
        buf[x1_]|=T[x1]&U[x2]
        return    
    buf[x1_]|=T[x1]
    buf[x2_]|=U[x2]        
    x1_+=+1
    while x1_<x2_:
        buf[x1_] = 0xffff
        x1_+=1


#### testing code ####

def clear():
    global buf
    buf=[0]*192*16

def render():
    for y in range(192):
        print "".join(bin(buf[(y<<4)+x])[2:].zfill(16) for x in range(16))


clear()
for y in range(0,192):
    drawline(y/2,y,y)
for x in range(10,200,6):
    drawline(x,x+2,0)
    drawline(x+3,x+5,1)
for y in range(-49,50):
    drawline(200-int((2500-y*y)**.5), 200+int((2500-y*y)**.5), y+60)
render()

1

আমার পাইথন উত্তরের একটি সি সংস্করণ এখানে সেক্ষেত্রে লুপের পরিবর্তে স্যুইচ স্টেটমেন্ট ব্যবহার করে এবং অ্যারে সূচকের পরিবর্তে পয়েন্টার বৃদ্ধি করে সূচি হ্রাস করা হয়েছে

কয়েকটি অতিরিক্ত নির্দেশাবলীর জন্য টি [x1 & 0xf] এবং ইউ [x2 এবং 0xf] ব্যবহার করে দেখার টেবিলের আকারটি যথেষ্ট পরিমাণে হ্রাস করা যেতে পারে

#include <stdio.h>
#include <math.h>

unsigned short T[] = {0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001,
                      0xffff, 0x7fff, 0x3fff, 0x1fff, 0x0fff, 0x07ff, 0x03ff, 0x01ff,
                      0x00ff, 0x007f, 0x003f, 0x001f, 0x000f, 0x0007, 0x0003, 0x0001};

unsigned short U[] = {0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff,
                      0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
                      0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff};

unsigned short buf[192*16];

void clear(){
    int i;
    for (i=0; i<192*16; i++) buf[i]==0;
}

void render(){
    int x,y;
    for (y=0; y<192; y++){
        for (x=0; x<256; x++) printf("%d", (buf[(y<<4)+(x>>4)]>>(15-(x&15)))&1);
        printf("\n");
    }
}

void drawline(int x1, int x2, int y){
    int y_ = y<<4;
    int x1_ = y_+(x1>>4);
    int x2_ = y_+(x2>>4);
    unsigned short *p = buf+x1_;

    if (x1_==x2_){
        *p|=T[x1]&U[x2];
        return;
        }

    *p++|=T[x1];
    switch (x2_-x1_){
    case 14: *p++ = 0xffff;
    case 13: *p++ = 0xffff;
    case 12: *p++ = 0xffff;
    case 11: *p++ = 0xffff;
    case 10: *p++ = 0xffff;
    case 9: *p++ = 0xffff;
    case 8: *p++ = 0xffff;
    case 7: *p++ = 0xffff;
    case 6: *p++ = 0xffff;
    case 5: *p++ = 0xffff;
    case 4: *p++ = 0xffff;
    case 3: *p++ = 0xffff;
    case 2: *p++ = 0xffff;
    case 1: *p++ = U[x2];
    }     
}


int main(){
    int x,y;
    clear();

    for (y=0; y<192; y++){
        drawline(y/2,y,y); 
    }

    for (x=10; x<200; x+=6){
        drawline(x,x+2,0);
        drawline(x+3,x+5,1);
    }

    for (y=-49; y<50; y++){
        x = sqrt(2500-y*y);
        drawline(200-x, 200+x, y+60);
    }
    render();
    return 0;
    }

এটা কত দ্রুত?
ব্যবহারকারী অজানা

@ ব্যবহারকারী অজানা, একটি স্ট্রিংয়ের টুকরো কত দিন? আমি মনে করি এটি গৃহীত উত্তরের চেয়ে দ্রুত হওয়া উচিত কারণ এটি কাজের পরিমাণ কিছুটা হ্রাস করতে একটি সারণী ব্যবহার করে। আপনি কেন তাদের চেষ্টা করে দেখেন না এবং আপনি কী খুঁজে পান তা আমাদের জানান?
gnibbler

1

স্কালা, 7 এস / 1 এম লাইন 4.1 এস / 1 এম লাইন

// declaration and initialisation of an empty field: 
val field = Array.ofDim[Short] (192, 16) 

প্রথম বাস্তবায়ন:

// util-method: set a single Bit:
def setBit (x: Int, y: Int) = 
  field (y)(x/16) = (field (y)(x/16) | (1 << (15 - (x % 16)))).toShort 
def line (x0: Int, x1: Int, y: Int) = 
  (x0 to x1) foreach (setBit (_ , y))

অভ্যন্তরীণ পদ্ধতি কলটি মুছে ফেলার পরে এবং কিছুক্ষণের জন্য লুপটি প্রতিস্থাপন করার পরে, স্কেল ২.৮ এর সাথে আমার 2 গিগাহার্টজ সিঙ্গল কোরে এটি 1 মিও বিভ্রান্ত হয়। ৪.১ সেকেন্ডে লাইনগুলি। পরিবর্তে প্রাথমিক 7s।

  def line (x0: Int, x1: Int, y: Int) = {
    var x = x0
    while (x < x1) {  
      field (y)(x/16) = (field (y)(x/16) | (1 << (15 - (x % 16)))).toShort
      x += 1
    }
  }

টেস্টকোড এবং প্রার্থনা:

// sample invocation:
line (12, 39, 3) 
// verification 
def shortprint (s: Short) = s.toBinaryString.length match {          
  case 16 => s.toBinaryString                                          
  case 32 => s.toBinaryString.substring (16)                           
  case x  => ("0000000000000000".substring (x) + s.toBinaryString)}

field (3).take (5).foreach (s=> println (shortprint (s)))            
// result:
0000000000001111
1111111111111111
1111111100000000
0000000000000000
0000000000000000

পারফরম্যান্স পরীক্ষা:

  val r = util.Random 

  def testrow () {
    val a = r.nextInt (256)
    val b = r.nextInt (256)
    if (a < b)
      line (a, b, r.nextInt (192)) else
        line (b, a, r.nextInt (192)) 
  }

  def test (count: Int): Unit = {
    for (n <- (0 to count))
      testrow ()
  }

  // 1 mio tests
  test (1000*1000) 

ইউনিক্স সরঞ্জাম সময়ের সাথে পরীক্ষিত, স্টার্টআপ-টাইম, সংকলিত কোড, কোনও জেভিএম-স্টার্ট-আপ ফেজ সহ ব্যবহারকারী-সময়ের তুলনা করে।

লাইনের সংখ্যা বাড়ানো দেখায় যে, প্রতিটি নতুন মিলিয়নের জন্য এটির জন্য বাড়তি ৩.৩ এস প্রয়োজন।

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