IT, Scala, Java, Web, Ubuntu

Look and say sequence is the sequence of numbers generated from the previous number by reading off the digits of which the number consists.

So the first number is 1 then there is one "1". one 1 -> 11
Now use the number "11" and there are two 1s. two 1s -> 21
21: one 2 and one 1 -> 1211
1211: one 1, one 2 and two 1s -> 111221
111221: three 1s, two 2s and one 1 -> 312211
312211: one 3, one 1, two 2s and two 1 -> 13112221
13112221: one 1, one 3, two 1s, three 2s and one 1 -> 1113213211

The Java programme code which reads off the given number can be written like

public static String LookAndSayUsingForLoop(final String number)
{
if (null == number || number.isEmpty())
{
return "";
}
int firstCharPosition = 0;
final StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < number.length(); i++)
{
if (number.charAt(firstCharPosition) != number.charAt(i))
{
//
// the char at the current position is not equal to the first char
// in the group of the equal chars so collect the chars
// from the first char position to just before the current position.
//
final String digitsFound = number.substring(firstCharPosition, i);
stringBuilder.append(digitsFound
.length())
.append(number
.charAt(firstCharPosition));
firstCharPosition = i; // set the new first char position
}
}
/* add the leftover */
stringBuilder.append(number
.substring(firstCharPosition,
number.length())
.length())
.append(number
.charAt(firstCharPosition));
return stringBuilder.toString();
}

It can be simpler if recursion is used.
The LookAndSayUsingForLoop method can be re-written like

private static String lookAndSayV1(final String number, final int position)
{
if (number.length() == position)
{
// reached the end which means every digit in the number is
// equal to one another so just read off the entire number.
return String.valueOf(number.length()) + number.charAt(0);
}
final char firstChar = number.charAt(0);
return firstChar == number.charAt(position) ?
// the current char equals to the first one so keep checking
lookAndSayV1(number, position + 1) :
// otherwise, read off until just before the current position
// then check from the current position
// calling this function itself again.
String.valueOf(number
.substring(0, position)
.length()) +
firstChar +
lookAndSayV1(number
.substring(position), 0);
}

The last line which returns an unmodifiable list object should use a new ArrayList object instead of directly using list.
Just making list unmodifiableList is not enough as the caller of this method can still modify the given parameter list
e.g.) Just have Collections.unmodifiableList(list); will result in

final List<String> resultList = new ArrayList<String>();
resultList.add(number);
final List<String> result = lookAndSayUsingList2(resultList, howMany);
// result.add("test"); // <- this does not work! runtime exception!
resultList.add("test"); // <- yet this does!!!
// Now the result has "test" at the end although it's unmodifiable List.
// It was modified using resultList.

If you don’t want to pass a List object, create another method and use it with the lookAndSayUsingList2() method.