JavaScript, 225 221 212 bytes
-9 bytes graças a Conor O'Brien
Observe que seus casos de texto entram em conflito entre si. Seu primeiro caso de teste começa no meio da espiral. Seu segundo caso de teste começa no meio da espiral. Eu fui com o seu primeiro caso de teste, porque foi o primeiro que vi. Você não editou sua pergunta há mais de um ano, desculpe a presunção.
Primeiro caso de teste:
9<-8<-7
| |
2<-1 6
| |
3->4->5
Segundo caso de teste:
2<-1<-6
| |
3->4->5
| |
7->8->9
Sem mais delongas, aqui está o código do golfe. Tenho 100% de certeza de que, se a comunidade lascar, isso poderá ser reduzido significativamente. Isso retorna uma matriz de várias linhas.
s=>eval("s=[...s.replace(/ /g,'')];i=0;k=j=1;a=[[],[],[]];b='00122210';c=b*100+'';for(;;){for(l=0;l<8;l++){if(!s[i])break;if(a[k][j]==s[i])s[i]=s[i].toUpperCase();a[k][j]=s[i];k=b[l];j=c[l];i++}if(!s[i])break}a")
Snippet de pré-certificação (imprime uma string de várias linhas no console). Observe o diferente no meu caso de teste nº 2 e no caso de teste nº 2 do OP (veja acima, se você ainda não o tiver):
(se alguém com mais experiência com trechos quiser corrigir isso na entrada HTML, sinta-se à vontade para editar isso, preciso ir para a cama).
f=
s=>eval("s=[...s.replace(/ /g,'')];i=0;k=j=1;a=[[],[],[]];b='00122210';c=b*100+'';for(;;){for(l=0;l<8;l++){if(!s[i])break;if(a[k][j]==s[i])s[i]=s[i].toUpperCase();a[k][j]=s[i];k=b[l];j=c[l];i++;g(a)}if(!s[i])break}a")
//replace argument here to change output
var arr = f("apples appeal");
function g(ar) {
var str = "";
for (x = 0; x < 3; x++) {
for (y = 0; y < 3; y++) {
str += ar[y][x] || " ";
}
str += "\n";
}
console.log(str);
}
Ungolfed e explicação
f=(input)=>{
//remove spaces
input = input.replace(/ /g, "");
//convert to array (so I can uppercase individual letters)
input = input.split("");
//position in input
var pos = 0;
//positions inside output
var xPos = 1;
var yPos = 1;
//output container (3 rows, 3 columns)
var arr = [[],[],[]];
//counterclockwise indexes for x
var xOrder = "00122210";
//counterclockwise indexes for y
//var yOrder = "12221000"
var yOrder = xOrder * 100 + "";
//loop infinitely (breaks when input[pos] is undefined)
for (;;) {
//loop around circle
for (var i = 0; i < 8; i++) {
if (!input[pos]) {
break;
}
//if item already in array equal next item in input, set next item in input to caps before
if (arr[xPos][yPos] == input[pos]) {
input[pos] = input[pos].toUpperCase();
}
//write or overwrite in array with current from input
arr[xPos][yPos] = input[pos];
//increment last because we do not prime our loops
xPos = xOrder[i];
yPos = yOrder[i];
pos++;
}
if(!input[pos]) {
break;
}
}
return arr;
}