Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Приглашаем принять участие в работе над нашей Wiki.
  • Наша рассылка: subscribe.ru, content.mail.ru и Google groups.
  • Есть желающие вести новостную ленту "В мире технологий"?
  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
   Начало   Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Найти в интервале [100,N] все целые числа, не содержащие повторяющихся цифр  (Прочитано 1716 раз)
0 Пользователей и 1 Гость смотрят эту тему.
hardasm
Читатель

ua
Offline Offline

« : 26-12-2011 22:18 » 

Моя идея: найти количество цифр числа, найти количество различных цифр числа. Если эти количества совпадают, то данное число не содержит повторяющихся цифр. Этим правилом пройти все числа от N до 100. На С++ написал - работает, на Ассемблере - не могу. Помогите, пожайлуста перевести на Асм для TASM!
Код: (C++)
//Найти в интервале от 100 до n все целые числа, не содержащие повторяющихся цифр
#include<iostream>
#include<clocale>
using namespace std;
// кол-во цифр числа
int numberOfDigits(int m)
{
        int i=0;
        for(; m!=0; i++)
                        m/=10;
        return i;
}
// кол-во различных цифр числа
int numberOfDifferDigits(int m)
{
        const unsigned peak=20;//максимальное кол-во цифр N-числа, с к-рым компилер может работать
        bool L[peak];
        for(int i=0; i<peak; i++) L[i]=0;
        do
        {
                L[m%10]=1;
                m/=10;
        } while(m!=0);
        unsigned uniq=0;//счётчик различных цифр числа:
        for(int i=0; i<peak; i++)
                uniq+=L[i];
        return uniq;
}
 
int main()
{
        setlocale(LC_ALL,"russian");
        cout<<"Введи число больше ста: ";
        int n; cin>>n;
        cout<<"Количество цифр числа: "<<numberOfDigits(n)<<'\n';
        cout<<"Количество различных цифр числа: "<<numberOfDifferDigits(n)<<'\n';
        while(n!=100)
        {
                if(numberOfDigits(n)==numberOfDifferDigits(n)) //если кол-во цифр числа равно кол-ву различных цифр числа, то это число не содержит повторяющихся цифр
                        cout<<n<<'      ';
                n--;
        }
        return 0;
}
Записан
Oldy
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 27-12-2011 04:33 » 

У С-компиляторов есть инструкция компиляции через (в) ассемблер. Попробуйте использовать ее. (У Borland C++ "-S")
« Последнее редактирование: 27-12-2011 06:35 от Oldy » Записан

С уважением, Oldy.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #2 : 27-12-2011 06:36 » 

Так, заметки в сторону Улыбаюсь
Код: (C++)
        const unsigned peak=20;//максимальное кол-во цифр N-числа, с к-рым компилер может работать
        bool L[peak];
        for(int i=0; i<peak; i++) L[i]=0;
В десятичной системе, обшее количество комбинаций чисел всего десять. Так что L[10] и далее просто бесмысленно. Да и еше больше можно убыстрить и упростить алгоритм. Деление довольно сложная и тяжеллая операция. Процессор выполняет ее в десятки раз дольше чем даже умножение.
« Последнее редактирование: 27-12-2011 06:38 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 27-12-2011 08:07 » 

Кроме того, организовывать полный перебор с проверкой... нерационально как-то.
Количество итоговых комбинаций будет сильно ниже, чем полное количество цифр в интервале. И все эти дорогостоящие проверки...
Не проще ли сразу подсчитывать количество возможных перестановок? То есть, алгоритмически, будет немного посложнее, конечно, но оно того стоит, я думаю.
Записан
hardasm
Читатель

ua
Offline Offline

« Ответ #4 : 29-12-2011 23:04 » 

В десятичной системе, обшее количество комбинаций чисел всего десять. Так что L[10] и далее просто бесмысленно. Да и еше больше можно убыстрить и упростить алгоритм. Деление довольно сложная и тяжеллая операция. Процессор выполняет ее в десятки раз дольше чем даже умножение.
Согласен, протупил

Добавлено через 48 секунд:
У С-компиляторов есть инструкция компиляции через (в) ассемблер. Попробуйте использовать ее. (У Borland C++ "-S")
А для Visual studio не подскажете?
« Последнее редактирование: 29-12-2011 23:05 от hardasm » Записан
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 30-12-2011 11:06 » 

У С-компиляторов есть инструкция компиляции через (в) ассемблер. Попробуйте использовать ее. (У Borland C++ "-S")
А для Visual studio не подскажете?
В зависимости от версии студии, возможны отличия, но в 2008й в настройках проекта есть "C/C++"->"Output files"->"Assembler Output", где нужно выбрать желаемое среди вариантов (ключ /FA с вариациями)
Записан
hardasm
Читатель

ua
Offline Offline

« Ответ #6 : 30-12-2011 18:36 » 

В зависимости от версии студии, возможны отличия, но в 2008й в настройках проекта есть "C/C++"->"Output files"->"Assembler Output", где нужно выбрать желаемое среди вариантов (ключ /FA с вариациями)
Спасибо, буду знать. (правда для меня это не выход: асм-файл весит аш 69кб, содержит 2тыщи строк, ладно буду думать. Если у кого-то что-то похожее найдётся, будьте людьми... спасибо)
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 30-12-2011 18:51 » 

hardasm, так он тебе, чтобы "подсмотреть как", а не для того, чтобы его взять и сдать. Улыбаюсь Халявы не будет.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Вад
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 30-12-2011 19:15 » 

hardasm, ты лучше ответь на вопрос:
Цитата
Не проще ли сразу подсчитывать количество возможных перестановок?
Просто пост начинался с твоей идеи, которая выглядит в корне неверной - в смысле, неэффективной. Или комбинаторику не проходили?
Записан
hardasm
Читатель

ua
Offline Offline

« Ответ #9 : 31-12-2011 17:30 » 

hardasm, ты лучше ответь на вопрос:
Цитата
Не проще ли сразу подсчитывать количество возможных перестановок?
Просто пост начинался с твоей идеи, которая выглядит в корне неверной - в смысле, неэффективной. Или комбинаторику не проходили?
проходили, в школе) С Новым Годом!
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #10 : 31-12-2011 17:43 » 

В школе проходят комбинаторику?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 01-01-2012 08:22 » 

Finch, в некоторых школах - да.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
hardasm
Читатель

ua
Offline Offline

« Ответ #12 : 06-01-2012 12:22 » 

Ну вот, на плюсах упростил (идея та же):
Код: (C++)
//Найти в интервале от 100 до n все целые числа, не содержащие повторяющихся цифр
#include<iostream>
#include<clocale>
using namespace std;

int main()
{
        setlocale(LC_ALL,"russian");
        cout<<"Введи число больше ста: ";
        int n; cin>>n;
        bool L[10]; // каждый "бит" этого массива отвечает за присутствие цифры в текущем числе
        for(int i=100;i<=n;i++)
        {
                for(int j=0; j<10; j++)
                        L[j]=0;
                int tmp=i;
                while(tmp!=0) // есть ли в числе разные цифры?
                {
                        if(L[tmp%10]!=0)
                                break;
                        L[tmp%10]=1;
                        tmp/=10;
                        if(tmp==0)
                                cout<<i<<' ';
                }
        }
        cout<<endl;
        return 0;
}
Пытаюсь стряпать аналог на ассемблере:
Код: (ASM)
        .model small
        .stack
        .data
n       dw      ?
LM      dw      ? ; как-бы аналог массива bool L[10]
ten     dw      10
ms      db      "Vvedi n>100:$"
        .code
extrn writer:near
extrn read:near
        .startup
; Выводим просьбу ввести n
mov ah,9
lea dx,ms
int 21h
call read
mov n,ax; запоминаем n

mov cx,100
next: ; как-бы аналог цикла for(int i=100;i<=n;i++)
        lea bx,LM
        add bx,20
        nuler:  ; заполним массив нулями
                mov [bx],0
                dec bx
                dec bx
                jnz nuler
                mov [bx],0
        inc cx
        mov ax,cx; сохраним cх
        proverka_chisla: ; есть ли в текущем числе разные цифры?
                ;cwd
                div ten; остаток от деления на 10 попадёт в dx
                ;lea bx,LM
                add dx,dx
                add bx,dx
                mov si,[bx]
                sub bx,dx
                cmp si,0
                jne next; если si не=0, значит в текущем числе уже есть цифра равная dx
                mov [bx],1
                cmp ax,0
                jne proverka_chisla
        mov ax,cx
        call writer
        cmp ax,n
        jne next

mov ah,1
int 21h
        .exit
        end
Ошибка: Divide overflow Понимаю, что идея далеко не самая эффективная, но мне сейчас главное "шоб работало" - на творчество нет времени Жаль. Помогите подправить С ума сойти..., пожалуйста.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #13 : 06-01-2012 12:59 » 

Код: (ASM)
        lea bx,LM
        add bx,20
        nuler:  ; заполним массив нулями
                mov [bx],0
                dec bx
                dec bx
                jnz nuler
                mov [bx],0
Вот тут переполнение налицо. Причем n тоже будет обнулен. Кстати для таких случаев есть замечательные команды. Работа с массивом байт.
Код: (ASM)
rep movsw
« Последнее редактирование: 06-01-2012 13:06 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
hardasm
Читатель

ua
Offline Offline

« Ответ #14 : 06-01-2012 13:24 » 

Код: (ASM)
        lea bx,LM
        add bx,20
        nuler:  ; заполним массив нулями
                mov [bx],0
                dec bx
                dec bx
                jnz nuler
                mov [bx],0
Вот тут переполнение налицо. Причем n тоже будет обнулен.
а как обнулится n, не пойму?
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #15 : 06-01-2012 16:36 » 

Посмотри команду movsw. Ну или если хочеш вручную, заведи в любом регистре счетчик и считай до 20.  Вернее от 20 до 0.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.16 | SMF © 2011, Simple Machines