中文题目: http://www.microsoft.com/technet/scriptcenter/funzone/games/games08/chs/aevent8.mspx
官方解题: http://www.microsoft.com/technet/scriptcenter/funzone/games/solutions08/apssol08.mspx
这个题目上来可能会让人觉得有点束手无策, 但是实际上这道题很简单, 题目允许的范围是75到80分钟, 而歌曲实际上范围还是很大的. 我们只要确定每位歌手只选择两首歌曲即可.
这道题, 我们可以将歌曲首先按照长度由长到短的顺序进行排列, 这样我们首先选择那些长的歌曲, 再选择短的歌曲来保证最后的播放列表能够满足75到80分钟的要求. 换句话说, 我们首先用较大的石头去填坑, 再用小石头把坑填好. 思路已经有了, 接下来我们需要实现代码:
$songs
=
Get
-
Content songlist
.
csv
|
`
%
{
$song
=
$_
.
Split
(
'
,
'
);
$hash
=
New
-
Object
-
TypeName HashTable
$hash
.
artist
=
$song
[
0
];
$hash
.
name
=
$song
[
1
];
$hash
.
time
=
[TimeSpan]
"
00:$($song[2])
"
;
$hash
}
$songs
=
$songs
|
Sort
-
Object
-
Property @{e
=
{
$_
.
time
};d
=
$true
}
$atimes
=
@{}
$low
=
New
-
TimeSpan
-
Minute
75
$high
=
New
-
TimeSpan
-
Minute
80
$total
=
New
-
TimeSpan
$cd
=
$(
foreach
(
$song
in
$songs
)
{
if
((
$total
-
ge
$low
)
-
and (
$total
-
le
$high
)) { break }
if
(
$atimes
[
$song
.
artist]
-
lt
2
)
{
if
((
$total
-
lt
$low
)
-
and ((
$total
+
$song
.
time
)
-
le
$high
))
{
$total
=
$total
+
$song
.
time
;
$atimes
[
$song
.
artist]
++
;
$song
}
}
})
|
Sort
-
Object
-
Property @{e
=
{
$_
.
artist}}
|
`
Select
-
Object
-
Property @{n
=
"
artist
"
;e
=
{
$_
.
artist}}
,
@{n
=
"
name
"
;e
=
{
$_
.
name}}
,
@{n
=
"
time
"
;e
=
{
$_
.
time
}}
$cd
|
%
{
$_
.
artist
+
"
`t
"
+
$_
.
name
+
"
`t
"
+
"
$($_.time.Minutes + $_.time.Hours * 60):$('{0:D2}' -f $_.time.Seconds)
"
}
""
"
Total music time: $($total.Minutes + $total.Hours * 60):$('{0:D2}' -f $total.Seconds)
"
每首歌曲被封装在hashtable对象中, 每首歌曲都用一个hashtable表示. 歌曲的长度用TimeSpan来表示, 因为TimeSpan已经完成了很多时间的计算, 我们完全可以不用考虑这些琐碎的细节.
接下来用Sort-Object对时间进行倒序, 因为使用TimeSpan, 所有PowerShell能够利用该对象完成比较, 我们不需要进行干涉. 每个歌手最多只能选择两首歌曲, 那么建立hash表进行记录是再好不过的决定. 对所有歌曲进行迭代, 如果歌曲加入后, 能够让结果趋向75到80分钟, 并且该名歌手还没有选满2首, 那么将改歌曲输出. 我们还需要主要进行排序工作和时间的统计.