Counting islands in a matrix from file - c

so I'm having trouble solving a problem for my IT exam.
I solved it and it partially worked but I could find a solution only using a BFS and I'm sure this doesn't require graph traversal algorithms since we haven't done them yet but I can't find any other solution. Could someone give me a hint.I'll post the BFS code down under just to how that I've actually solved this but not how I think it should've been solved.
#include <stdio.h>
#include <stdlib.h>
char file[20][20];
int v[20], ns, n, comp, c[20];
int prim;
int ultim;
FILE *f;
int nr = 0, nl, nc;
void matrix() {
int i, j;
char c, n;
fscanf(f, "%d %d \n", &nl, &nc);
for (i = 1; i <= nl; i++) {
for (j = 1; j <= nc; j++) {
c = getc(f);
file[i][j] = c;
}
n = getc(f);
}
}
// citirea grafului din fisier text si construirea matricei de adiacenta
// afisarea pe ecran a matricei de adiacenta
void afisare() {
int i, j;
printf("Matricea : \n");
for (i = 1; i <= nl; i++)
{
for (j = 1; j <= nc; j++)
printf("%c", file[i][j]);
printf("\n");
}
}
// returnează primului nod nevizitat
int exista_nod_nevizitat(int v[20], int n) {
int i, j;
for (i = 1; i <= nl; i++)
if (v[i] == 0)
return i; // primul nod nevizitat
return 0; // nu mai exista noduri nevizitate
}
// parcurgerea în latime a unei componente conexe, plecând din nodul de start ns
void parcurgere_latime(char file[20][20], int nl, int ns) {
int i, j;
comp++;
v[ns] = 1;
prim = ultim = 1;
c[ultim] = ns;
while (prim <= ultim) {
for (i = 1; i <= nl; i++)
if (file[c[prim]][i] == 'L')
if (v[i] == 0)
{
ultim++;
c[ultim] = i;
v[i] = 1;
}
prim++;
}
}
// functia principala main()
int main() {
int set, nr;
f = fopen("in1.txt", "r");
fscanf(f, "%d \n", &set);
while (set != 0) {
matrix();
afisare();
while (exista_nod_nevizitat(v, n) != 0) {
ns = exista_nod_nevizitat(v, n);
parcurgere_latime(file, n, ns); // parcurg o alta componenta conexa
}
printf("Graful este alcătuit din ");
printf("%d", comp);
printf("componente conexe \n");
set--;
}
return 0;
}

Found this solution which seems to be easier and faster
int countIslands(char a[100][100])
{
int count = 0;
for ( i=0; i<nl; i++)
{
for (j=0; j<nc; j++)
{
if (a[i][j] == 'L')
{
if ((i == 0 || a[i-1][j] == '.') &&
(j == 0 || a[i][j-1] == '.'))
count++;
}
}
}
return count;
}

I'll type out a pretty basic solution which comes to mind. Note that it is not certainly not optimal and is a bit of a brute-force approach.
Basically, what I'm thinking of is traversing the matrix element by element, and every time you find an L (beginning of the island), find its borders by going from neighbour to neighbour and marking it down with the number of the current island until there's no more neighbours for the elements of the island, then continue traversing the matrix, repeating the same steps every time you find an L that has not been marked.

Related

Count number of elements in array after placing them in ascending order

I'm creating a program that reads input from an array and orders it in an ascending order. However, I also wanted to count the number of times each element appears in the array, but I'm struggling to to this. This is the code I have so far:
#include <stdlib.h>
#include <locale.h>
typedef enum _ordem {
Crescente=1
} ordem;
void troca(int *x, int *y){
int wk;
wk=*x;*x=*y;*y=wk;
}
int trocar(int x, int y, ordem dir){
if(dir == Crescente)
return x > y;
return 0;
}
void bubbleSort(int *array, int top, int fim, ordem dir){
int i, j, trocado;
for(i = top; i < fim; ++i){
trocado = 0;
for(j = top + 1; j <= fim - i; ++j)
if(trocar(array[j-1], array[j], dir)){
troca(&array[j-1], &array[j]);
trocado = 1;
}
if(trocado == 0)break;
}
}
int main(){
int vetor[100], index, ordem=1;
index=0;
setlocale(LC_ALL,"Portuguese");
printf("Introduza os números. Escreva -00 para parar. \n");
do{
scanf("%d", &vetor[index++]);
}while(vetor[index-1] != -00 && index < 100);
--index;
bubbleSort(vetor, 0, index-1, ordem);
{
int i;
for(i=0;i<index;++i)
printf("%d ", vetor[i]);
printf("\n");
}
return 0;
}
After the numbers have been sorted, equal numbers will be next to each other in the array. This makes it easy to count the number of times each number occurs using a single loop that iterates through the sorted array, with an extra variable that is incremented when the next element has the same number as the current element, or is reset when the next element has a different number.
The following block of code will do that:
{
int i, c;
c = 1;
for (i = 0; i < index; ++i) {
if (i < index - 1 && vetor[i] == vetor[i + 1]) {
c++;
} else {
printf("%d(x%d) ", vetor[i], c);
c = 1;
}
}
printf("\n");
}
You could create another array to store a table of the unique values with their frequency of occurrance:
struct freq {
int val;
int freq;
};
struct freq freq[100];
int nfreq = 0;
Fill the table using a loop similar to the earlier code:
{
int i, c;
c = 1;
for (i = 0; i < index; ++i) {
if (i < index - 1 && vetor[i] == vetor[i + 1]) {
c++;
} else {
freq[nfreq].val = vetor[i];
freq[nfreq].freq = c;
nfreq++;
c = 1;
}
}
}
Print the out the table with another simple loop:
{
int i;
for (i = 0; i < nfreq; i++) {
printf("%d(x%d) ", freq[i].val, freq[i].freq);
}
printf("\n");
}

How to find out the inverse of an NXN matrix in C

Hi everyone I made some changes in the code so that it's easy to understand, looks what I have so far, I kept the function's prototype at the beginning of the code and it works fine, but it just works fine just when I try a 2x2 matrix because if I try a 3x3, 4x4 or 6x6 matrix it does not works fine the determinant is not calculated right, I guess that's the problem the determinant but I don't know how to solve it. Here is the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<math.h>
float determinant(int tam,float [][tam]);
void cofactor(int tam,float [][tam]);
void transpose(int tam,float [][tam],float [][tam]);
int validate(){
int val;
char *buf = (char *) malloc(10);
memset(buf,0,10);
while(fgets(buf, 10, stdin) != NULL ){
if(buf[0]!='\n') {
val = atoi(buf);
break;
}
}
free(buf);
return val;
}
float determinant(int tam, float matrix[][tam])
{
float s = 1, det = 0, b[tam][tam];
int i, j, m, n, c;
if (tam == 1)
{
return (matrix[0][0]);
}
else
{
det = 0;
for (c = 0; c < tam; c++)
{
m = 0;
n = 0;
for (i = 0;i < tam; i++)
{
for (j = 0 ;j < tam; j++)
{
b[i][j] = 0;
if (i != 0 && j != c)
{
b[m][n] = matrix[i][j];
if (n < (tam - 2))
n++;
else
{
n = 0;
m++;
}
}
}
}
det = det + s * (matrix[0][c] * determinant( tam - 1,b));
s = -1 * s;
}
}
return (det);
}
void cofactor( int tam,float num[][tam])
{
float b[tam][tam], fac[tam][tam];
int p, q, m, n, i, j;
float x = 0;
for (q = 0;q < tam; q++)
{
for (p = 0;p < tam; p++)
{
m = 0;
n = 0;
for (i = 0;i < tam; i++)
{
for (j = 0;j < tam; j++)
{
if (i != q && j != p)
{
b[m][n] = num[i][j];
if (n < (tam - 2))
n++;
else
{
n = 0;
m++;
}
}
}
}
x = pow(-1, q + p) * determinant( tam - 1,b);
fac[p][q] = x;
}
}
transpose(tam,num, fac);
}
void transpose(int tam,float num[][tam], float fac[][tam])
{
int i, j;
float b[tam][tam], inverse[tam][tam], d;
for (i = 0;i < tam; i++)
{
for (j = 0;j < tam; j++)
{
b[i][j] = fac[j][i];
}
}
d = determinant(tam,num);
for (i = 0;i < tam; i++)
{
for (j = 0;j < tam; j++)
{
inverse[i][j] = b[i][j] / d;
}
}
printf("\n\n\nThe inverse of matrix is : \n");
for (i = 0;i < tam; i++)
{
for (j = 0;j < tam; j++)
{
printf("\t%f", inverse[i][j]);
}
printf("\n");
}
}
int verify_Size(int line){
if((line > 0) && (line <= 6))
{
return 1;
}
return 0;
}
int create_Matrix(int LINE){
int matrix[LINE][LINE];
float aux[LINE][LINE];
printf("\n\n\nPle:", (LINE * LINE));
printf("\n--------------------------------\n");
for(int i=0;i<LINE;i++)
{
for(int j=0;j<LINE;j++)
{
printf("Value[%d][%d]: ",i,j);
matrix[i][j] = validate();
}
}
printf("\n\nYour Bidimensional Matrix is:");
printf("\n--------------------------------\n");
for(int i=0;i < LINE;i++)
{
for(int j=0; j< LINE;j++)
{
printf("\t%2d",matrix[i][j]);
aux[i][j] = (float) matrix[i][j];
}
printf("\n");
}
float d = determinant(LINE,aux);
printf("\n\nDeterminante Main: %f \n",d);
if (d == 0)
printf("\nInverse of Entered Matrix is not possible\n");
else
cofactor(LINE,aux);
return 0;
}
int main(){
int flag,line;
do{
printf("Enter the order of the Matrix:\n");
printf("-------------------------------\n");
printf("Lines: ");
line = validate();
if(verify_Size(line)== 1)
{
create_Matrix(line);
}else{
printf("\nMatrix must to be till 6 X 6!\n");
flag = 0;
}
}while(flag != 1);
return 0;
}
It looks like you are finding the inverse matrix by Cramer's rule. While it works Ok for 2x2 or 3x3 matrix sizes, the hard part about implementing Cramer's rule generally is evaluating determinants. If you compute an NxN determinant following the definition, the computation is recursive and has factorial O(N!) computational complexity (Wikipedia).
I suggest switching to another algorithm. LUP factorization is fast and relatively simple, and Wikipedia has an example implementation.

I'm getting this error: Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

I need help here! I'm trying to code a console-based C program which solves several systems of equations.
Exercise:
The program receives an entry file (input and output file names typed in by the user), containing n, m, and a bunch of numbers which will fill in a matrix. This matrix is an extended matrix which has n rows and n+m columns (where m is the number of systems to solve). First "submatrix" nxn must be reduced using Gauss Elimination method with pivoting.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int gauss_pivot (double **a, int n, int m, double tol);
void resol (double **a, int n, int m);
int main(void) {
double **ampliada;
int n, m;
int i, j;
FILE *entrada, *sortida;
char nomE[31], nomS[31];
printf("Noms dels fitxers d'entrada i sortida\n");
scanf("%s %s", nomE, nomS);
entrada = fopen(nomE, "r");
sortida = fopen(nomS, "w");
if (entrada == NULL || sortida == NULL){
if (entrada == NULL){
printf("Error en el fitxer d'entrada\n");
exit(1);
}
else{
printf("Error en el fitxer de sortida\n");
exit(1);
}
}
fscanf(entrada, "%d", &n);
fscanf(entrada, "%d", &m);
ampliada = (double**)malloc(n*sizeof(double*));
if (ampliada == NULL) {
printf("Memòria insuficient\n");
exit(1);
}
for (i=0; i<n; i++){
ampliada[i] = (double*)malloc(m*sizeof(double));
if (ampliada[i] == NULL){
printf("Memòria insuficient\n");
exit(1);
}
}
for (i=0; i<n; i++){
for (j=0; j<=m; j++){
fscanf(entrada, "%le", &ampliada[i][j]);
}
}
gauss_pivot(ampliada, n, m, 10^(-16));
resol(ampliada, n, m);
return 0;
}
int gauss_pivot (double **a, int n, int m, double tol){
float q;
double pivot, aux;
int r;
for (int j = 0; j < n; j++){
pivot = 0;
for (r = j; r < n; r++){
if (fabs(a[r][j]) > pivot){
pivot = a[r][j];
}
}
if (pivot != a[j][j]){
for (int s = 0; s < (n+m); s++){
aux = a[r][s];
a[r][s] = a[j][s];
a[j][s] = aux;
}
}
for (int i = 0; i < n; i++){
if(i > j){
q = a[i][j]/a[j][j];
for (int k = 0; k < (n+m); k++){
a[i][k] = a[i][k] - q*a[j][k];
}
}
}
}
return 0;
}
void resol (double **a, int n, int m){
double resultats[n], suma;
for (int s = 1; s <= m; s++){
printf("Solució al sistema %d:\n", s);
resultats[n]=a[n][n+1]/a[n][n];
for(int i = n-1; i >= 1; i--){
suma=0;
for(int j=i+1; j<=n; j++){
suma=suma+a[i][j]*resultats[j];
}
resultats[i]=(a[i][n+1]-suma)/a[i][i];
}
for (int r = 1; r <= n; r++){
printf("X_%d = %f", r, resultats[r]);
}
}
}
It crashes on the following lines (sometimes one, somtimes the other):
aux = a[r][s];
a[r][s] = a[j][s];
a[j][s] = aux;
And I get the following error message:
Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
What am I doing wrong?

How to save in a file in C

#include "Header.h"
void mostraTabuleiro(int lin, int col, int **m){
int i, j, l;
char k = 65;
for (l = 1; l <= col; l++){
printf("\t%c", k);
k++;
}
printf("\n");
for (i = 1; i <= lin; i++){
printf("%d", i);
for (j = 1; j <= col; j++){
if (i == lin && j == col)
printf("\t[X]");
else
printf("\t[*] ");
}
printf("\n");
}
}
and now i want to save the mostratabuleiro in a file and i started doing this
int GuardaFicheiro(char *nome_fich){
FILE *fnovo;
char *novo_fich = "estadosTabuleiro.txt";
fnovo = fopen(novo_fich, "wt");
if (fnovo == NULL){
printf("Erro ao abrir o ficehiro de texto %s para escrita.\n", novo_fich);
return;
}
//mostraTabuleiro(6, 8, Tabuleiro, fnovo);
fclose(fnovo);
}
if i put fprintf in the function mostraTabuleiro after that it doesn't appera anything and the file is blank.
This should be corrected
fnovo = fopen(novo_fich, "wt");
into:
fnovo = fopen(novo_fich, "w");
after that use fprintf();
fprintf(fnovo, /*source char * */);
You may please note that you should ask question on S.O. in this style. You can also read this.
void mostraTabuleiro(int lin, int col, int **m, FILE *fnovo) {
int i, j, k;
for (k = 1; k <= col; k++){
fprintf(fnovo, "\t%d", k);
}
fprintf(fnovo, "\n");
for (i = 1; i <= lin; i++){
fprintf(fnovo, "%d", i);
for (j = 1; j <= col; j++){
if (i == lin && j == col)
fprintf(fnovo, "\t[X]");
else
fprintf(fnovo, "\t[*] ");
}
fprintf(fnovo, "\n");
}
}
and
void GuardaFicheiro(int lines, int columns, int **m){
FILE *fnovo;
char *novo_fich = "estadosTabuleiro.txt";
fnovo = fopen(novo_fich, "wt");
if(fnovo == NULL){
printf("error opening file %s for writing.\n", novo_fich);
return;
}
// this will write to the file
mostraTabuleiro(lines, columns, m, fnovo);
// this will write on screen : stdout
mostraTabuleiro(lines, columns, m, stdout);
fclose(fnovo);
}
and
int iniciaJogo() {
tabuleiro tab;
int i, j, m, n;
int res = 0;
int **Tabuleiro;
int cont = 0;
int iteracoes = 0;
do{
do{
printf("Dimensoes do ambiente\nLines\n");
scanf("%d", &tab.N_Linhas);
} while (tab.N_Linhas < 4 || tab.N_Linhas > 8);
do{
printf("Columns\n");
scanf("%d", &tab.N_Colunas);
} while (tab.N_Colunas < 6 || tab.N_Colunas > 10);
} while (tab.N_Linhas > tab.N_Colunas);
Tabuleiro = criaTabuleiro(tab.N_Linhas, tab.N_Colunas);
GuardaFicheiro(tab.N_Linhas, tab.N_Colunas, Tabuleiro);
//mostraTabuleiro(tab.N_Linhas, tab.N_Colunas, Tabuleiro, fnovo);
}
And, may be main like:
int main(){
iniciaJogo();
return 0;
}
I am sure the above code would work for you. But you should read little about C Programming - functions, structures, and FileIO.
There are many unused variables in your code, you may check compiling your code with gcc -Wall -Wextra yourFileName.c

How do I continuously write to and read from the same file in C

I am trying to store the coordinates (x, y) in a text file, where x denotes the row number and y the column. I will then use this information to change the element of the array to 1, and the others will remain at 0. I want to do this multiple times to the same .txt file. I'm trying to simulate the famous Game of Life. The trouble is that is only successfully reads from the file once so the array cannot update, and so the array just prints off the same stuff as before.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROWS 30
#define COLS 20
#define ITERATIONS 6
int fillBoard(int b[ROWS][COLS]);
int newRound(FILE *i, int b[ROWS][COLS]);
int cellAliveOrDead(FILE *p, int b[ROWS][COLS]);
int cellBirth(FILE *p, int b[ROWS][COLS]);
int main(void) {
int board[ROWS][COLS];
char fileName[] = "#life 1.06";
int i, j;
int x, y;
int round = 0;
FILE *fp, *ifp;
char fileFormat[11];
int p, o;
fp = fopen("life.txt", "r");
ifp = fopen("life2.txt", "r");
if (fp == NULL) {
printf("Error\n");
exit(1);
}
if (ifp == NULL) {
exit(1);
}
fillBoard(board);
fgets(fileFormat, 11, fp); // read input from first line
if (strcmp(fileName, fileFormat) == 0) {
while (fscanf(fp, "%d %d", &x, &y) == 2) {
board[x][y] = 1;
printf("x:%d y:%d\n", x, y);
}
} else {
printf("Wrong file");
}
// print game with the starter cells
for (i = 0; i < ROWS; i++) {
printf("\n");
for (j = 0; j < COLS; j++) {
printf("%d", board[i][j]);
}
}
newRound(ifp, board);
fclose(fp);
fclose(ifp);
return(0);
}
int newRound(FILE *ij, int b[ROWS][COLS]) {
int round = 0;
int x, y;
int i, j;
while (round < ITERATIONS) {
printf("\n");
cellAliveOrDead(ij, b);
cellBirth(ij, b);
fillBoard(b);
while (fscanf(ij, "%d %d", &x, &y) == 2) {
b[x][y] = 1;
printf("x:%d y:%d\n", x, y);
}
round++;
// print game round 2
for (i = 0; i < ROWS; i++) {
printf("\n");
for (j = 0; j < COLS; j++) {
printf("%d", b[i][j]);
}
}
}
}
int fillBoard(int b[ROWS][COLS]) {
int i, j;
for(i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
b[i][j] = 0;
}
}
}
int cellAliveOrDead(FILE *p, int b[ROWS][COLS]) {
int count;
int i, j;
for(i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
count = 0;
if(b[i][j] == 1) {
if(b[i-1][j] == 1) count++;
if(b[i+1][j] == 1) count++;
if(b[i][j-1] == 1) count++;
if(b[i][j+1] == 1) count++;
if(b[i-1][j-1] == 1) count++;
if(b[i-1][j+1] == 1) count++;
if(b[i+1][j-1] == 1) count++;
if(b[i+1][j+1] == 1) count++;
if(count == 2 || count == 3) {
//b[i][j] = 1;
fprintf(p, "%d %d\n", i, j);
}
}
}
}
}
int cellBirth(FILE *p, int b[ROWS][COLS]) {
int count;
int i, j;
for(i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++) {
count = 0;
if (b[i][j] == 0) {
if(b[i-1][j] == 1) count++;
if(b[i+1][j] == 1) count++;
if(b[i][j-1] == 1) count++;
if(b[i][j+1] == 1) count++;
if(b[i-1][j-1] == 1) count++;
if(b[i-1][j+1] == 1) count++;
if(b[i+1][j-1] == 1) count++;
if(b[i+1][j+1] == 1) count++;
if (count == 3) {
//b[i][j] = 1;
fprintf(p, "%d %d\n", i, j);
}
}
}
}
}
The simplest answer would be to use 2 files.
Write into a FILE* A. Then close it and read it as FILE* B, and write into a FILE* A. Repeat.
The other method would be to use fseek. This is quite risky as the chances of you rewriting on top of essential information is quite possible. But follow this answer, and you should be fine.
Also see this if you are curious about how fseek works.

Resources