БлогNot. 15 не пригодившихся задачек за декабрь-2015

15 не пригодившихся задачек за декабрь-2015

Что накопилось и может ещё пригодиться. Везде C/C++, все коды проверялись в Visual Studio 2010 или 2015. Для быстрого поиска нужного слова на странице используйте в браузере комбинацию клавиш Ctrl+F.

1. Составить программу для "графического" изображения делимости чисел от 1 до n. В каждой строке консоли напечатать очередное число и перечислить все делители этого числа.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h> 
 
int main() {
 int n=100,i,j;
 for (i=1; i<=n; i++) {
  printf ("\n%d: ",i);
  for (j=1; j<=i; j++) if (i%j==0) printf ("%d ",j);
 }
 fflush(stdin); getchar(); return 0;
}

2. Дан одномерный массив. Определить минимальное счастливое число среди чисел с четным количеством цифр. Счастливое число - это число, у которого сумма цифр первой половины числа равна сумме второй половины.

Пример того, как "красиво" найти количество цифр в целом числе (count_digits).

#include <stdio.h>
#include <limits.h>
 
int count_digits (long int num){ return ( num /= 10 ) ? 1 + count_digits(num) : 1; }
 
int happy_digit (long int num) {
 //работает и для нечетного количества цифр
 int sum1=0,sum2=0,i=0,n=count_digits(num);
 if (n<2) return 0;
 while (num!=0) {
  if (i<n/2) sum1 += num%10;
  else if (!(n%2==1 && i==n/2)) sum2 += num%10;
  num/=10;
  i++;
 }
 return sum1==sum2;
}
 
int main (){
 const int n = 7;
 long int a[n] = { 4224, 1324, 132, 434, 123321, 4004, 12 };
 long int min=LONG_MAX,c;
 int i;
 for (i=0; i<n; i++) {
  c=count_digits(a[i]);
  if (c%2==0 && happy_digit(a[i]) && a[i]<min) min=a[i];
 }
 printf ("\n%ld",min);
 fflush (stdin);
 getchar ();
 return 0;
}

3. Дан символ C и строки S, S0. Перед каждым вхождением символа C в строку S вставить строку S0 (используются си-строки, а не класс string).

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
//if s[i]==c, insert s0 before it. no memory control!
char *strins (char *s, char *s0, char c) {
 int slen=strlen(s);
 int s0len=strlen(s0);
 int i,j;
 for (i=0; i<slen; i++) {
  if (s[i]==c) {
   for (j=slen; j>=i; j--) s[j+s0len]=s[j];
   for (j=0; j<s0len; j++) s[i+j]=s0[j];
   slen+=s0len; i+=s0len;
  }
 }
 return s;
}
 
int main (){
 char c='l';
 const int SIZE=256;
 char *s = (char *)malloc(SIZE*sizeof(char));
 strcpy(s,"lol, Hello, i'm test string! la-la-l");
 char *s0 = "123";
 char *ptr = strins(s,s0,c);
 puts(ptr);
 fflush (stdin);
 getchar ();
 return 0;
}

Функция strins, согласно условиям задачи, не контролирует использование оперативной памяти.

4. Занести в одномерный массив значения функции f(x,y) = (x + y)2, 0<=x<=5, 0<=y<=3, и вывести его на экран.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
double f(double x, double y) { return pow(x+y,2); }
 
int main (){
 double x1=0,x2=5,y1=0,y2=3,dx=1,dy=1; //границы по x,y и шаги
 int n=ceil((x2-x1+1)/dx)*ceil((y2-y1+1)/dy); //размерность массива, необязательно точная
 double *fa=(double *)malloc(n*sizeof(double));
 double x,y;
 int i=0;
 for (x=x1; x<=x2+1e-9; x+=dx) 
 for (y=y1; y<=y2+1e-9; y+=dy) fa[i++]=f(x,y);
 int j;
 for (j=0; j<i; j++) printf ("%.2lf ",fa[j]);
 fflush (stdin);
 getchar ();
 return 0;
}

5. Написать функцию вычисления F(N) = F(N-2)+3.5, с использованием рекурсии, при условии F(1)=1, F(0)=0.

#include <stdio.h>
 
double f(int n) { 
 if (n<1) return 0;
 else if (n<2) return 1;
 else return f(n-2)+3.5; 
}
 
int main (){
 for (int i=0; i<10; i++) printf ("f(%d)=%.2lf ",i,f(i));
 fflush (stdin);
 getchar ();
 return 0;
}

6. Транспонировать прямоугольную матрицу a[n][m] с выделением памяти для новой матрицы.

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
 
int **transp (int n, int m, int **a) { //a[n][m] => at[m][n]
 int **at=(int**)malloc(m*sizeof(int *));
 int i,j;
 if (at==NULL) return NULL;
 for (i=0; i<m; i++) {
  at[i]=(int*)malloc(n*sizeof(int));
  if (at[i]==NULL) return NULL;
  
 }
 for (i=0; i<n; i++) for (j=0; j<m; j++) at[j][i]=a[i][j];
 return at;
}
 
void print_matrix(int n,int m,int **a) {
 int i,j;
 for (i=0; i<n; i++) {
  printf ("\n");
  for (j=0; j<m; j++) printf ("%d ",a[i][j]);
 }
}
 
int main () {
 const int n=3,m=2;
 int **a,i,j;
 a=(int**)malloc(n*sizeof(int *));
 for (i=0; i<n; i++) a[i]=(int*)malloc(m*sizeof(int));
 a[0][0]=1; a[0][1]=2;
 a[1][0]=3; a[1][1]=4;
 a[2][0]=5; a[2][1]=6;
 print_matrix(n,m,a);
 int **at=transp(n,m,a);
 print_matrix(m,n,at);
 fflush(stdin); getchar(); return 0;
}

7. Для заданного натурального n, например n=4, сформировать матрицу вида

1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3 

#include <iostream> 
using namespace std;
 
int main() {
 const int n=10;
 int a[n]={1,2,3,4,5,6,7,8,9,10};
 int a1[n][n],i,j;
 
 for (int i=0; i<n; i++) {
  int start = i;
  for (j=0; j<n; j++) {
   a1[i][j] = a[start++];
   if (start>n-1) start=0;
  }
 }
 
 for (i = 0; i < n; i++) {
  for (j = 0; j < n; j++) cout << a1[i][j] << ' ';
  cout << endl;
 }       
 
 cin.sync(); cin.get(); return 0;
}

8. Среди заданных натуральных чисел найти такие, десятичная запись которых не содержит одинаковых цифр.

#include <iostream> 
using namespace std;
 
int different_digits (int n) {
 int d[10],i;
 for (i=0; i<10; i++) d[i]=0;
 while (n) {
  if (d[n%10]++) break;
  n/=10;
 }
 return (n?0:1);
}
 
int main() {
 cout << 1234 << ": " << different_digits (1234) << endl;
 cout << 3213 << ": " << different_digits (3213) << endl;
 cout << 100 << ": " << different_digits (100) << endl;
 cout << 98170 << ": " << different_digits (98170) << endl;
 cin.sync(); cin.get(); return 0;
}

Здесь симпатична функция different_digits, возвращающая 1, если все цифры числа разные. Обратите внимание, что break срабатывает именно при d[n%10] (количество вхождений очередной цифры), большем 1, а не 0.

9. Используя рекурсивную функцию, найти сумму первых n элементов последовательности x[n] = 3 * x[n-1]+1, x[0] = 1.

#include <iostream> 
using namespace std;
 
int x(int n) { return (n==0 ? 0 : 3*x(n-1)+1); }
 
int main() {
 int sum=0;
 const int n=10; //сколько элементов суммировать
 for (int i=0; i<n; i++) {
  cout << x(i) << endl;
  sum+=x(i);
 }
 cout << "sum=" << sum << endl;
 cin.sync(); cin.get(); return 0;
}

10. Сравнить попарно все строки в матрице и вывести номера отличающихся пар строк.

#include <iostream> 
using namespace std;
 
int main() {
const int n=3,m=2;
 int a[n][m]={
 {1,2},
 {2,3},
 {1,2}
 };
 for (int i=0; i<n-1; i++)
 for (int j=i+1; j<n; j++) {
  int r=0;
  for (int k=0; k<m; k++) if (a[i][k]!=a[j][k]) { r=1; break; }
  cout << "strings " << i << " and " << j << " are " <<
   (r ? "not" : "") << " equal" << endl;
 }
 cin.sync(); cin.get(); return 0;
}

11. Найти порядковый номер наибольшего по значению элемента массива, являющегося симметричным в десятичном представлении.

#define _CRT_SECURE_NO_WARNINGS /*for Visual C++ 2015*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h> //В Borland C было values.h
 
int count_digits(int num) { //цифр в числе
    return (num /= 10) ? 1 + count_digits(num) : 1; 
}
 
int symmetric_number(int n) { //1, если число симметрично
    int count = count_digits(n),i;
    char *digits = (char *)malloc(count*sizeof(char));
    if (!digits) return 0;
    for (i = 0; i < count; i++) {
        digits[count-i-1] = abs(n % 10); //если число отрицательно - смотрим без знака
        n /= 10;
    }
    if (count == 1) return 1; //числа 0-9 считаем симметричными
    for (i = 0; i < count/2; i++) {
        if (digits[i] != digits[count-i-1]) return 0;
    }
    free (digits);
    return 1;
}
 
int main() {
    const int n = 8;
    int a[n] = { 1, 55, 31200, 676, 4884, 30503, 31412, 29692 };
    int i, nmax, max = -INT_MAX; //В Borland C было MAXINT
    for (i = 0; i < n; i++) {
        if (symmetric_number(a[i]) && a[i]>max) {
            max = a[i]; nmax = i + 1;
        }
    }
    printf("\nvalue=%d (number=%d)",max,nmax);
    fflush(stdin); getchar(); return 0;
}

P.S. Формально INT_MIN != -INT_MAX:

#define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
#define INT_MAX       2147483647    /* maximum (signed) int value */

INT_MIN на 1 больше по модулю (7FFFFFFF или -2147483648 для 32 бит).

Так что код не сработает, только если массив заполнен одними значениями INT_MIN :) Возможно, и INT_MIN+1, т.к., сравнение ">", а не ">=".

Но эти числа всё равно несимметричные :)

Да и в Борланде "MININT", вроде бы, не было.

12. Задан массив m типа int и его размерность n. Найти значение максимального элемента массива без использования каких-либо операторов цикла.

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <math.h>
using namespace std;
 
int maxi(int n, int *m)     {
 if (n > 0) return max(m[n], maxi(--n,m));
 else if(n == 0) return m[0];
}
 
int main() {
 const int n=10;
 int m[n] = {3,2,1,3,9,4,6,7,8,4};
 cout << maxi(n,m);
 
 cin.sync(); cin.get(); return 0;
}

Можно, конечно, пошутить и сделать с goto:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
 
int main() {
 const int n=10;
 int m[n] = {5,2,1,3,9,4,6,7,8,2};
 int i = 0, max = m[0];
 l1:
 if(max < m[i]) max = m[i];
 i++;
 if(i >= n) goto l2;
 goto l1;
 l2:
 
 cout << max << endl;
 cin.sync(); cin.get(); return 0;
}

13. Переставить 3-й и 4-й биты младшего байта целого числа с помошью программного кода.

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <bitset>
using namespace std;
 
int main() {
 int n=42;
 
 cout << n << " (" << bitset<32>(n) << ")" << endl;
 //нумерация бит в байте: 7654 3210
 int b3 = n&8, b4 = n&16; 
 n &= ~(1<<3); 
 if (b4) n|=(1<<3);
 n &= ~(1<<4); 
 if (b3) n|=(1<<4);
 cout << n << " (" << bitset<32>(n) << ")" << endl;
  
 cin.sync(); cin.get(); return 0;
}

Действия между операторами cout можно выполнить и в 4 оператора вместо 6 (первый код тоже поддаётся сокращению):

int b3 = ((n>>3) & 1);
int b4 = ((n>>4) & 1);
n = (n & (~0x18));
n |= ((b3<<4) | (b4<<3));

14. Определить наименьшее число сравнений, нужное для сортировки 4 значений по возрастанию.

Это число равно пяти, а не шести, как может показаться, если привыкнуть сравнивать каждый элемент с каждым (трудоёмкость этого действия соответствует количеству элементов выше или ниже главной диагонали квадратной матрицы размерностью n*n и равна (n2 - n)/2 = 6 при n=4).

Например, можно за 3 сравнения упорядочить 3 первых числа, потом среднее из чисел сравнить с оставшимся, и, в зависимости от результатов этого сравнения, выполнить ещё одно.

В доказательство возьмём все возможные комбинации чисел 1,2,3,4 и проверим на них функцию sort4, содержащую ровно 5 условных операторов.

Заодно main показывает, как реализовать стандартными средствами все перестановки элементов массива (вначале различные между собой элементы массива a должны быть упорядочены по возрастанию, чтоб сработал стандартный алгоритм).

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
using namespace std;

void swap (int &a, int &b) { int c=a; a=b; b=c; }

void sort4 (int &a, int &b, int &c, int &d) {
 if (a>b) swap(a,b);
 if (a>c) swap(a,c);
 if (b>c) swap(b,c); //за 3 сравнения сортируются 3 числа 
 if (b>d) { //сравнить среднее с 4-м
  swap(b,d);
  if (a>b) swap (a,b);
  swap(c,d);
 } 
 else if (c>d) swap(c,d);
}

int main () {
 int a[] = { 1, 2, 3, 4 };
 int len = sizeof(a) / sizeof(int);
 int *b = new int [len];
 do {
  cout << "From:";
  for (int i = 0; i < len; i++) {
   cout << a[i] << ",";
   b[i] = a[i]; //копия массива, так как в sort4 передаем по ссылке
  }
  sort4 (b[0],b[1],b[2],b[3]);
  cout << " to: ";
  for (int i = 0; i < len; i++) cout << b[i] << ",";
  cout << endl;
 } while (next_permutation (a, a + len));
 delete[] b;
 
 cin.sync(); cin.get(); return 0;
}

15. Поменять местами содержимое старшего и младшего байтов двухбайтового целого значения.

Работаем с типом short int, чтобы обеспечить 2 байта. Обратите внимание, как вывести число в двоичном виде стандартными средствами C++.

#include <iostream> 
#include <bitset>
using namespace std;

short int swapbytes(short int a) {
 return ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8);
}

int main() {
 short int a = -32767;
 cout << a << " (" << bitset<16>(a) << ")" << endl;
 a = swapbytes(a);
 cout << a << " (" << bitset<16>(a) << ")" << endl;
 cin.sync(); cin.get(); return 0;
}

Естественное, казалось бы,

 return (a<<8) + (a>>8);

сработает только для положительных значений.

29.12.2015, 10:12 [15023 просмотра]


теги: учебное список c++ алгоритм

показать комментарии (1)