回答編集履歴

1

別解の追記

2020/06/12 09:32

投稿

fana
fana

スコア11663

test CHANGED
@@ -69,3 +69,125 @@
69
69
  }
70
70
 
71
71
  ```
72
+
73
+
74
+
75
+ ---
76
+
77
+
78
+
79
+ 質問内容とは直接関係ないけど,せっかくだからnewが不要な簡単な方法を追記.
80
+
81
+
82
+
83
+ ```C++
84
+
85
+ //パケットを2つに分けるが,splitとは戻り値と引数が異なる(逆な感じ)関数.
86
+
87
+ //渡されたパケットを,上側n枚 と 残り の2つのパケットに分けて
88
+
89
+ //前者側のトップを指すポインタを戻り値とする.
90
+
91
+ //headは後者側のトップを指す値に更新される.
92
+
93
+ Card *split2( Card *&head, int n )
94
+
95
+ {
96
+
97
+ Card *p = split( head, n );
98
+
99
+ std::swap( p, head );
100
+
101
+ return p;
102
+
103
+ }
104
+
105
+
106
+
107
+ //new不要なやりかた
108
+
109
+ Card *dealn2(Card *head,int n)
110
+
111
+ {
112
+
113
+ //結果のカードは机上に積んでいくものとする
114
+
115
+ Card *DesktopPile = nullptr;
116
+
117
+ //まず右手にデックを持つ
118
+
119
+ Card *RHS_Packet = head;
120
+
121
+ //左手は最初は空である
122
+
123
+ Card *LHS_Packet = nullptr;
124
+
125
+ //---
126
+
127
+ int nSkip = n;
128
+
129
+ while( true )
130
+
131
+ {
132
+
133
+ --nSkip;
134
+
135
+ while( RHS_Packet )
136
+
137
+ {
138
+
139
+ //右手のパケットのトップからnSkip枚のカードを取り上げ,それを
140
+
141
+ //左手のパケットのボトム側に付け加える
142
+
143
+ if( nSkip>1 )
144
+
145
+ {
146
+
147
+ Card *SkippedCards = split2( RHS_Packet, nSkip );
148
+
149
+ if( SkippedCards )
150
+
151
+ {
152
+
153
+ if( LHS_Packet ){ pileup( LHS_Packet, SkippedCards ); }
154
+
155
+ else{ LHS_Packet = SkippedCards; }
156
+
157
+ }
158
+
159
+ }
160
+
161
+ //右手にカードが残っていないならループを抜ける
162
+
163
+ if( !RHS_Packet )break;
164
+
165
+ //右手のパケットのトップのカードを机上の山のトップに移す(重ねる)
166
+
167
+ Card *CardToDeal = split2( RHS_Packet, 1 );
168
+
169
+ pileup( CardToDeal, DesktopPile );
170
+
171
+ DesktopPile = CardToDeal;
172
+
173
+ }
174
+
175
+
176
+
177
+ //左手にカードが無いなら終了
178
+
179
+ if( !LHS_Packet )break;
180
+
181
+ //左手にあるパケットをそのまま右手に移す
182
+
183
+ RHS_Packet = LHS_Packet;
184
+
185
+ LHS_Packet = nullptr;
186
+
187
+ }
188
+
189
+ return DesktopPile;
190
+
191
+ }
192
+
193
+ ```