質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

671閲覧

数字の各桁を足して合計が大きい順に並び替える

wanwanko

総合スコア14

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2021/11/23 16:02

今現在、ネットで見つけたC言語の問題を解いているのですが、知識面と技術面が足りなくて、なかなか思うようにかけません。
問題は、
入力した五つの数字、それぞれ各桁を足して合計を求め、合計が大きい順(降順)に並び替える、(但し和が同じ場合は元の数字が小さい方が先)という問題です。
例えば
input
1919810
87654312
29393091
12345678
94789487

上記の数字ぞれぞれの各桁の和は29,36,36,36,56で更に元の数字が小さい方が先ということも考慮すると
output
94789487
12345678
29393091
87654312
1919810
という出力になります。

元の数字の各桁の和を求めて、和を降順にしたコードは書けたのですが、この問題は和の降順を出力するのが問題ではなく、それぞれ各桁の和を求めて和が大きい元の数字を並び替えるもので、そこがうまく書けません。

どなたかヒントをいただけたら嬉しいです。私はどの分野の知識が足りてないですか?

#include <stdlib.h> int cmpnum(const void * n1, const void * n2) { if (*(int *)n1 > *(int *)n2) { return -1; } else if (*(int *)n1 < *(int *)n2) { return 1; } else { return 0; } } int main(){ int num,dig,N,arr[100]; scanf("%d",&N); for(int i=0;i<N;++i){ scanf("%d",&num);//1919810 87654312 29393091 12345678 94789487 int sum=0; while(num){ dig = num % 10;//各桁の値を求める sum = sum + dig;//各桁をたす num = num / 10; } arr[i]=sum; } qsort(arr, N, sizeof(arr[0]), cmpnum); for (int i = 0; i < N; i++) printf("%d ", arr[i]); printf("\n"); return 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

自分だったらどうするか、という形での回答をさせていただきます。

自分であれば以下の構造体を作ります。

struct CombNumberSum { int number; // 入力した数字を格納 int sum; // 入力した数字の桁の合計 }

ヒントが欲しいということなので、この程度の回答とさせていただきます。

投稿2021/11/23 16:28

rinjinto

総合スコア170

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wanwanko

2021/11/23 18:22

ありがとうございます!構造体を使って模索したいと思います!!!
episteme

2021/11/23 18:55

「私はどの分野の知識が足りてないですか?」のコタエになってるかしら?
wanwanko

2021/11/24 01:38

素直に実装するというのが答えかと思いました
rinjinto

2021/11/24 01:56

不足してるものは「発想力」だと判断しました。 これは経験を積んでいくことで培われることが可能なものです。 ですので、ヒントを出してそこから想像してもらうことで発想力を培ってもらおうと思いました。 ベストアンサーにされた実装は実は問題点があります。 それに気付けるでしょうか?
rinjinto

2021/11/24 02:00

(問題点というほど大きなものではないですね。)
episteme

2021/11/24 02:24

つまりは 「足りないのは知識ではない」ってことです。
episteme

2021/11/24 02:41

構造体を定義するこの実装にも問題点があります。 それに気付けるでしょうか?
guest

0

足りないのは、知識ではなく、思考力だと思います。

桁の和の配列を作ってそれをソートしようとしても、和が同じ場合、元の数が必要です。
元の数とその桁の和という、2つの値をひとまとめにして配列にしないと
いけないと考えるのが普通です。

2つの値をひとつにまとめるのに、構造体の知識があればそれを使えます。
その構造体の配列を用意すればいいのです。

2つの値がともに int であることを考えれば、要素数 2 の配列でも構いません。
その配列の配列を用意すればいいのです。

あと必要な知識は、配列とポインタの関係でしょう。

c

1#include <stdio.h> // scanf, printf 2#include <stdlib.h> // qsort 3 4int cmpnum(const void *n1, const void *n2) 5{ 6 int *a = (int*)n1, *b = (int*)n2; 7 if (a[0] < b[0]) return 1; 8 if (a[0] > b[0]) return -1; 9 if (a[1] < b[1]) return -1; 10 if (a[1] > b[1]) return 1; 11 return 0; 12} 13 14int main(void) 15{ 16 int num, N, arr[100][2]; 17 scanf("%d", &N); 18 for (int i = 0; i < N; ++i) { 19 scanf("%d", &num); 20 arr[i][1] = num; 21 arr[i][0] = 0; 22 while (num) { 23 arr[i][0] += num % 10; 24 num /= 10; 25 } 26 } 27 qsort(arr, N, sizeof(arr[0]), cmpnum); 28 for (int i = 0; i < N; i++) 29 printf("%d ", arr[i][1]); 30 printf("\n"); 31 return 0; 32}

このコードは理解できますか?

追記
2つの値(32ビットint)をひとつにまとめるのに、long long(64ビット) を
使うことを考えてみましょう。
和は降順、数値は昇順ですから、和を符号反転すると、比較関数が簡単になります。

C

1#include <stdio.h> // scanf, printf 2#include <stdlib.h> // qsort 3 4int cmpnum(const void *n1, const void *n2) 5{ 6 long long a = *(long long *)n1, b = *(long long *)n2; 7 return a < b ? -1 : a > b; 8} 9 10int main(void) 11{ 12 int num, N; 13 long long arr[100]; 14 scanf("%d", &N); 15 for (int i = 0; i < N; ++i) { 16 scanf("%d", &num); 17 long long sum = 0; 18 for (int n = num; n; n /= 10) sum += n % 10; 19 arr[i] = -sum << 32 | num; // 和は降順、数は昇順 20 } 21 qsort(arr, N, sizeof(arr[0]), cmpnum); 22 for (int i = 0; i < N; i++) 23 printf("%lld ", arr[i] & 0xffffffff); 24 printf("\n"); 25 return 0; 26}

投稿2021/11/24 00:22

編集2021/11/24 07:09
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wanwanko

2021/11/24 06:55

わかりやすくコードを提供してくださりありがとうございます????
wanwanko

2021/11/24 06:56

あの、arr[i] = -sum << 32 | num; の行って何をしている行ですか?
kazuma-s

2021/11/24 07:08

64ビットの long long の上位 32ビットに和の符号を変えたものを置いて、下位32ビットに元の数を置いています。ビット演算の知識はまだないということですか? 最初の配列の配列を使うほうのコードは理解できたのでしょうか?
guest

0

ベストアンサー

「それぞれ各桁を足して合計を求め、合計が大きい順(降順)に並び替える、
(但し和が同じ場合は元の数字が小さい方が先)」を素直に実装:

C

1#include <stdio.h> 2#include <stdlib.h> 3 4int sum_digit(int num) { 5 int sum=0; 6 while(num){ 7 int dig = num % 10;//各桁の値を求める 8 sum = sum + dig;//各桁をたす 9 num = num / 10; 10 } 11 return sum; 12} 13 14int cmpnum(const void * n1, const void * n2) { 15 // 各桁の和が 16 int d1 = sum_digit(*(int *)n1); 17 int d2 = sum_digit(*(int *)n2); 18 // 大きい方が先 19 if ( d1 > d2 ) return -1; 20 else if ( d1 < d2 ) return 1; 21 else { // 同じなら、 22 // 元の数が小さい方が先 23 if (*(int *)n1 > *(int *)n2) return 1; 24 else if (*(int *)n1 < *(int *)n2) return -1; 25 } 26 return 0; 27} 28 29int main(){ 30 int N, arr[100]; 31 ... 32 qsort(arr, N, sizeof(arr[0]), cmpnum); 33 ... 34 return 0; 35}

投稿2021/11/23 17:47

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

wanwanko

2021/11/23 18:22

ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問