궁금 왜 라인for 루프에서 ToList 메서드를 사용하지 않으면 왜 실패합니까?
"sub = sub.SelectMany(x => x.Next(i)).ToList();"
"sub = sub.SelectMany(x => x.Next(i));"
로 변경하면 나는 오류를 얻을
행 48 : System.IndexOutOfRangeException : 인덱스의 범위를 벗어난 배열 "을 입력하면 SolveNQueens 메서드에 4가 입력됩니다.
나는 게으른 평가와 관련이 있다고 생각합니다.
전체 코드 샘플은 아래에 나열되어 있으며 n queens 문제에 대한 유효한 해결책입니다. 이것이 실패
public class Solution {
public IList<IList<string>> SolveNQueens(int n)
{
IEnumerable<PartialQueens> sub = new List<PartialQueens>(){
new PartialQueens(n)};
for(int i=0;i<n;i++)
{
sub = sub.SelectMany(x => x.Next(i)).ToList();
}
return sub.Select(x => x.ToPosition()).ToList();
}
}
public class PartialQueens
{
public byte FREE = 0;
public byte BLOCKED = 1;
public byte QUEEN = 2;
public byte[,] fill;
int n;
public PartialQueens(int n)
{
this.n = n;
fill = new byte[n,n];
}
public PartialQueens(byte[,] fill, int n)
{
this.fill = fill;
this.n = n;
}
public PartialQueens Fill(int row, int column)
{
byte[,] newFill = fill.Clone() as byte[,];
newFill[row,column] = QUEEN;
Action<int,int> f = (x,y) =>
{
if(y >= 0 && y < n)
newFill[x,y] = BLOCKED;
};
for(int i=1;i<n-row;i++)
{
f(row+i,column+i);
f(row+i,column-i);
f(row+i,column);
}
return new PartialQueens(newFill,n);
}
public IEnumerable<PartialQueens> Next(int row)
{
for(int j=0;j<n;j++)
{
if(fill[row,j] == FREE)
yield return Fill(row,j);
}
}
public IList<string> ToPosition()
{
return Enumerable.Range(0,n).Select(i => ConvertRow(i)).ToList();
}
public string ConvertRow(int i)
{
StringBuilder builder = new StringBuilder();
for(int j=0;j<n;j++)
{
if(fill[i,j] == QUEEN)
builder.Append("Q");
else
builder.Append(".");
}
return builder.ToString();
}
}
[이 문제에 대한 추가 정보] (https://blogs.msdn.microsoft.com/ericlippert/2009/11/12/closing-over-the-loop-variable-considered-harmful/) – StuartLC
감사합니다. 흠뻑! 나는 closure가 C#에서 이런 방식으로 수행된다는 것에 놀랐다. –
많은 사람들이이를 결함으로 간주하고 MS는 'foreach'루프에서 유사한 문제를 수정하기 위해 큰 변화를 겪었습니다. 문제는 for 루프에 있지만, 루프에 대한 FP 패러다임은 Range로 더 잘 표현 될 수 있습니다. 내가 편집 할게. – StuartLC