مسألة برمجية للتدريب (تحتاج معرفة Binary)

  • Rashadoo

المشكلة تقول كالتالي:

سأعطيك رقمين n , m يمكن من 1 الى 10 قوة 18 .. اريد عدد الارقام التي بينهما (معهما) التي تحوي في تمثيلها الثنائي (الباينري) صفراً واحداً


مثال على الدخل :

n = 5

m = 10

الخرج : 2

لان 5 = 101

و 6 = 110

وباقي الارقام الى عشرة تحوي اكثر من صفر او لا تحوي اصفاراً ابداً


مثال ثاني:

2015 2015

الخرج : 1


مثال اخير :

72057594000000000 72057595000000000

الخرج : 26

يرجى الدخول لحسابك أو تسجيل حساب لتستطيع إضافة تعليق
حساب جديد دخول

التعليقات

محمد عزيز الكناني أضف ردا

خوازميتي

lowerbound, upperbound = map(int, raw_input().split())
c = 0
for i in range(len(bin(lowerbound))-2, len(bin(upperbound))-1):
    s = ['1'] * i
    for j in range(len(s)-1):
        k = s[:]
        k[len(k)-1-j] = '0'
        k = int(''.join(k), 2)
        if (k<=upperbound) and (k>=lowerbound):
            c += 1
print c

تعمل على الامثلة التي أدخلتها 

لا أعرف ان كانت الحل الافضل ولكن هذا أفضل ماأستطيع التفكير فيه حاليا.

أظن أن الخوارزمية سريعة كفاية (ان لم اخطئ في حساب التعقيد)

   O(log2(m)^2)

أيضا شكرا على التمارين الجيدة.

هل يمكنك كتابة الخوارزمية pseudo code

لا افهم البايثون

مثالك الاول

محصور بين 5 و 10

يعني

101

و 1010

تقوم بالبحث في 111

بتبديل مكان الصفر كل مرة يعني

110

101

ثم في 1111

1110

1101

1011

وتدرج فقط الارقام في ال range n..m

طبعا في أسوء الحالات ال loop الاول ستدور 60 مرة

لان binary representation الخاصة ب 10^18 متكونة من 60 رقم على الاكثر

بالنسبة لل loop الاخرى ستدور في اسوء الحالات 59 مرة

يعني البرنامج كامل سيقوم بعمل 59*60 = 3540 دورة

يعني التعقيد هو

O(log2(m)^2)

الذي هو جيد جدا ولكني متأكد أني أستطيع عمل شئ أسرع

قلت لك لا تنشرها :(

هذا ما كنت أريد تجربته لاكن كنت أبحث عن الدالة التي تحول بين أنضمة العد في JavaScript

ووجدتها الآن

(10e18).toString(2)

حاول بالمسألة الاخرى .. ضاعت طعمة هذه هههه

فكّرتُ في هذا الحل قبل قليل بعدما خرجت من المنزل هههه وكنت أرغب بمُراسلة @Rashadoo للتأكّد من أنّ هذه هي الخوارزميّة الصّحيحة -لأنّني لم أتمعّن في شيفرتك جيّدا-.

على العموم مُحاولتي لحلّ هذه المسألة قد فشلت :)

يبدو ان هناك احد قد **** من هذه المسألة ولم يعرف الحل فقام بالتسليب ههه

لا اعلم لم اخذ تسليبات دائماً على هذه المسائل هل انت سبامر ؟

ان لم تكن ارجوك قل لي السبب

ربما يكون السبب عدم وضوح العنوان.

يجب أن يفهم الزائر المشاركة بقراءة العنوان فقط. لا تدخل عناوين غير واضحة مثل: "موضوع مهم"، "استفسار بسيط"، "مشكلة أرجو المساعدة"

في مثل هذه الحالة، لا يمكن إزالة الإلتباس عن كنه الموضوع بعنوانه، إلا إذا كتبت المسألة كاملة في العنوان!

عبد الهادي أضف ردا

مُحاولتي:

def count_valid_numbers(n, m):
    valid_num = 0
    while n <= m:
        count_zeros = bin(n)[2:].count('0')
        if count_zeros == 1:
           valid_num += 1
        n += 1
    return valid_num

جرّبت الشيفرة على المثالين الأول والثاني فقط، وكانت النّتيجة صحيحة. بالنّسبة للمثال الأخير فلا أظنّ أنّه سينتهي إلا بعد بضعة سويعات :(

@محمد عزيز الكناني الشيفرة الخاصّة بك طويلة نوعا ما، وهل جرّبتها مع المثال الأخير؟ قُمت بتجربتها منذ مدّة ولا زالت قيد التّنفيذ إلى الآن، أعتقد بأنّ سُرعتا الدّالتين مُتشابهتان.

@Rashadoo هل لك بأن توفر بعض الأمثلة الأخرى لأجرّب بها خوارزميّتي؟

ان فشلت في الاخير ففكرة خوارزميتك خاطئة .. صحيح انها تحل المسألة لكن لا احد سينتظر ساعة ليحصل على الجواب .. عندما انشر طريقة الحل المثال الاخير سيعطي الجواب في ميلي ثانية ..

1 - 100

16


1000000000000000000 1000000000000000000

0


1 1000000000000000000

1712 

@عبد الهادي ربما الخلل من عندك يعمل عادي في جهازي على كل الامثلة وارى أن خورزميتي هي الاسرع لحد الان..

سيعطي الجواب في ميلي ثانية

تقصد أنّه لن يدور على جميع الأعداد واحدا واحدا أم ماذا؟

نعم لن يبحث عن الاعداد واحداً واحداً

هل تريد حلا يقوم ب m-n عملية :)

هذه المرة قد لا يخرج المتصفح من حلقة التكرار ههه

لا تعقيد حلي لا يتعدى ال 264 الف عملية في اسوء الاحوال

هذا بطئ جدا.

@Rashadoo حلى أسرع بكثير 3600 عملية

لم افهم كودك هل لك ان تكتب الخوارزمية ؟

وهل جربت المثال الاخير ؟

نعم يعمل طبعا

ساكتب وصفا لفكرتي

في الحين يمكنك التجريب على هذا الموقع

حسنا إنتظر قليلا لدي فكرة سأجربها

Rashadoo أضف ردا

طيب بما انك من قسم الرياضيات اليك هذه المسألة الرياضية البحتة


سأقوم بادخال عدد n يدل على عدد مدن مشاركة في الحرب ويمكن ان يكون عددها من 1 الى مئة الف

كل المدن ستبعث عدداً جميلاً من الدبابات .. حيث ان العدد الجميل هو العدد ال1ي يتكون من اصفار وواحد فقط ولا يوجد على يساره اصفار .. الا مدينة واحد على الاكثر ستبعث عدداً غير جميل (اي عدد يحتوي على اكثر من واحد او يحتوي على ارقام غير الواحد والصفر)

سأدخل لك n رقم كل واحد سيدل على عدد الدبابات التي ستشارك بها الدول .. اطبع لي ناتج الضرب ... علماً ان عدد خانات عدد الدبابات لاي دولة يتكون من واحد الى مئة خانة


مثال دخل:

5 10 1

خرج : 50


مثال دخل :

11 1 10

خرج : 110

zakariamouhid أضف ردا
function sol(arr) {
    "use strict";
    var i = 0,
        j = 0,
        ziro = "",
        but = "1";
    while (i < arr.length) {
        if (arr[i].indexOf("1") !== arr[i].lastIndexOf("1") ||
            arr[i].indexOf("2") !== -1 ||
            arr[i].indexOf("3") !== -1 ||
            arr[i].indexOf("4") !== -1 ||
            arr[i].indexOf("5") !== -1 ||
            arr[i].indexOf("6") !== -1 ||
            arr[i].indexOf("7") !== -1 ||
            arr[i].indexOf("8") !== -1 ||
            arr[i].indexOf("9") !== -1
           ) {
            /* ليس جميل arr[i] */
            but = arr[i];
        } else {
            /* جميل arr[i] */
            ziro += arr[i].slice(1);
        }
        i += 1;
    }
    return but + ziro;
}

الحل ب JavaScript مثال

sol(["1","10","5"])

الخرج : "50"

إذا كنت ستضع العدد الغير جميل دائما في المكان الأول فيمكن جعل الكود أقصر

الفكرة صحيحة توجد العدد غير الجميل وتضع امامه اصفار .. لكن هل عالجت حالة ان يكون احد الارقام صفراً

هل سيكون ناتج الضرب صفراً :P

لم افهم ما كتبته في indexof و lastindexof

  • لم أعالج حالة الصفر

  • بالنسبة ل indexof و lastindexof فهي تتحقق هل العدد يحتوي على رقم 1 أكثر من مرة

 public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String a = sc.nextLine();
     String b = sc.nextLine();
     int count=0;
     int zeroCount=0;
      String binary="";
      char[] binaryChar=null;
      boolean bool=true;
      int j=0;
      long aa = Long.parseLong(a);
      long bb = Long.parseLong(b);
      long i = aa;
      while(i<=bb){
         binary = Long.toBinaryString(i);
          binaryChar = binary.toCharArray();
            int len = binary.length();
            while (bool & j!=len){
                if (binaryChar[j]=='0'){
                    zeroCount++;
                }
                if (zeroCount>1){
                 bool=false;
             }
             j++;
           }
           bool = true;
           j = 0;
           if (zeroCount == 1){
                count++;
            }
            zeroCount=0;
            i++;
   }
       System.out.println(count);
   }

تعقيد ضخم جداً .. اقرأ التعليقات ستعرف الحل الامثل

ما رأيكم بهذا ؟

def subin(dec) :
    zeros = 0

    while dec > 0:
        if zeros == 2:
            return False

        if dec % 2 == 0:
            zeros += 1

        dec //= 2

    return zeros == 1;

s = 0
for i in range(1, 10):
    if subin(i):
        s += 1
print('sum:', s)

output

sum: 3

اقرأ التعليقات .. تعقيدط كبير جداً

قلت ان الدخل 10 قوة 18 وحاسوب شخصي خارق يحتاج ساعة لمعالجة خوارزميتك

لا أعلم، هل المسألة مكتوبة خطأً، ولكن هناك من حل المسألة. أو أني لم أفهم المسألة، فقد حاولت فهم هذه الجملة قدر المستطاع ولم أفهم:

اريد عدد الارقام التي بينهما (معهما) التي تحوي في تمثيلها الثنائي (الباينري) صفراً واحداً

حاولت أن أفهم من أحد الحلول التي قدمها بعض المشاركين، فأجدها إما بلغة بايثون، أو جافا سكربت (والتي لا أعرف كيف ينفذ برنامجها).

أقرأ مثالك الأول، فأظن أن الحل هو معرفة عدد الخانات المختلفة بين العددين (في الصيغة الثنائية)، ولكن المثال الثاني ينسف ذلك تمامًا. وأما الأخير فهو لا يوضح شيئًا البتة (لمن لم يفهم المثالين السابقين)!

سأعطيك رقمين .. والمسألة هي ان تجد عدد الارقام بين هذين الرقمين التي اذا قمت بتحويلها الى الصيغة القنائية ستجد صفراً واحداً في صيغتها الثنائية

لغة روبي , xmax المدخل الاكبر , xmin المدخل الاصغر

سرعة .. O(log2(m)) بحيث m المدخل الاكبر

اداء الذاكرة O(1)

إن شاء الله يكون الحل صحيح

xmax = 6
xmin = 5

startRange = Math.log2(xmin).ceil
endRange = Math.log2(xmax).ceil

biggestNumber = (2**endRange)-1
smallestNumber = (2**startRange)-1

count  = 0
powerNumber = 1

for i in 0...(endRange-1)
    bnumber = biggestNumber-powerNumber
    snumber = smallestNumber-powerNumber


    if ((bnumber <= xmax and bnumber >= xmin) or 
         (snumber <= xmax and snumber >= xmin))
        count += 1
    end
    powerNumber = powerNumber * 2
end


puts "Result: #{count}"