@SuppressWarnings("deprecation")
	public static NeuralNet[] learnTiles(WritableRaster[] wrs, char[] ls, int nInps, NeuralNetListener listener) {
		assert (wrs.length == ls.length);
		int[] colCharInd = colCharInd();
		int[][] colIndChar = colIndChar();
		// Find out how many tiles there are of each letter
		int[] nLet = new int[26];
		for (int i = 0; i < ls.length; i++) {
			nLet[ls[i] - 'a']++;
		}
		// Find the minimum number letters for each colour
		int[] nCol = new int[7];
		for (int i = 0; i < 7; i++) {
			int min = Integer.MAX_VALUE;
			for (int j = 0; j < colIndChar[i].length; j++) {
				int n = nLet[colIndChar[i][j]];
				if (n < min) {
					min = n;
				}
			}
			nCol[i] = min;
		}
		// Seven sets, one for each colour, lsOutByCol will hold the letter
		// number per colour. For example 'c' is 1 because it is the 2nd letter
		// of colour 2. This is then stored as [0,1,0,0,0].
		// inpsByCol holds the network input for each tile of each colour.
		// Finally nLetByCol to record a count of each letter processed.
		double[][][] lsOutsByCol = new double[7][][];
		double[][][] inpsByCol = new double[7][][];
		int[][] nLetByCol = new int[7][];
		for (int i = 0; i < 7; i++) {
			lsOutsByCol[i] = new double[nCol[i] * colIndChar[i].length][colIndChar[i].length];
			inpsByCol[i] = new double[nCol[i] * colIndChar[i].length][nInps];
			nLetByCol[i] = new int[colIndChar[i].length];
		}
		int[] done = new int[7];
		for (int i = 0; i < ls.length; i++) {
			int col = WordBuilder.charColours[ls[i] - 'a'];
			// See if we're allowed any more of this letter in the training set
			nLetByCol[col][colCharInd[ls[i] - 'a']]++;
			if (nLetByCol[col][colCharInd[ls[i] - 'a']] <= nCol[col]) {
				// Store in first unused space (given by done
				// count) for the colour. Here we use colCharInd to find
				// the network output number for the letter.
				lsOutsByCol[col][done[col]] = iToOutputArray(colIndChar[col].length, colCharInd[ls[i] - 'a']);
				// Now preprocess and store the network input for this tile.
				ImageManagement.extWhite(wrs[i]);
				ImageManagement.remHighlights(wrs[i]);
				ImageManagement.magicWand(wrs[i]);
				wrs[i] = ImageManagement.autoCrop(wrs[i]);
				inpsByCol[col][done[col]] = ImageManagement.rasterToNetInput(wrs[i], nInps);
				done[col]++;
			}
		}
		// Train a net for each colour
		NeuralNet[] out = new NeuralNet[7];
		for (int i = 0; i < 7; i++) {
			System.out.println("Training colour " + i + "\nData includes:");
			// for (int j = 0; j < inpsByCol[i].length; j++) {
			// System.out.print("Tile " + j + " of " + inpsByCol[i].length);
			// System.out.println(" is letter ");
			// for (int k = 0; k < colIndChar[i].length; k++) {
			// System.out.print(lsOutsByCol[i][j][k] + ", ");
			// }
			// System.out.println(":");
			// ImageManagement.printNetInput(inpsByCol[i][j], nInps);
			//			}
			assert lsOutsByCol[i].length == inpsByCol[i].length;
			NeuralNet nnet = hiddenLNet(nInps, colIndChar[i].length, inpsByCol[i].length, listener);
			nnet.setParam("colour", Integer.toString(i));
			// Now add the training data
			MemoryInputSynapse memInp = new MemoryInputSynapse();
			memInp.setFirstCol(1);
			memInp.setLastCol(nInps);
			nnet.getInputLayer().addInputSynapse(memInp);
			memInp.setInputArray(inpsByCol[i]);
			TeachingSynapse trainer = new TeachingSynapse();
			MemoryInputSynapse samples = new MemoryInputSynapse();
			samples.setFirstCol(1);
			samples.setLastCol(colIndChar[i].length);
			samples.setInputArray(lsOutsByCol[i]);
			trainer.setDesired(samples);
			nnet.getOutputLayer().addOutputSynapse(trainer);
			nnet.setTeacher(trainer);
			nnet.go(true, true);
			out[i] = nnet;
		}
		return out;
	}