Skip to Content

Bovine Genomics

Análisis oficial (C++) 

Solución en video

Por Jay Fu

Video de YouTube (Oh_952B03xE)

Código de la solución en video
#include <cmath> #include <fstream> #include <iostream> using namespace std; int N, M; string spotty[100], plain[100]; bool test_location(int j) { bool found_cow[2][4] = {0}; // found_cow[0] se refiere a las vacas con manchas, y found_cow[1] a las // vacas sin manchas. found_cow[0][0] = guarda si las vacas con manchas tienen el carácter A en // la posición j found_cow[0][1] = guarda si las vacas con manchas tienen el carácter C // en la posición j found_cow[0][2] = guarda si las vacas con manchas tienen el carácter // G en la posición j found_cow[0][3] = guarda si las vacas con manchas tienen el // carácter T en la posición j found_cow[1][0] = guarda si las vacas lisas tienen // el carácter A en la posición j found_cow[1][1] = guarda si las vacas lisas tienen // el carácter C en la posición j found_cow[1][2] = guarda si las vacas lisas tienen // el carácter G en la posición j found_cow[1][3] = guarda si las vacas lisas tienen // el carácter T en la posición j // iteramos por las vacas con manchas y actualizamos found_cow[0] for (int i = 0; i < N; i++) { if (spotty[i][j] == 'A') found_cow[0][0] = true; if (spotty[i][j] == 'C') found_cow[0][1] = true; if (spotty[i][j] == 'G') found_cow[0][2] = true; if (spotty[i][j] == 'T') found_cow[0][3] = true; } // iteramos por las vacas lisas y actualizamos found_cow[1] for (int i = 0; i < N; i++) { if (plain[i][j] == 'A') found_cow[1][0] = true; if (plain[i][j] == 'C') found_cow[1][1] = true; if (plain[i][j] == 'G') found_cow[1][2] = true; if (plain[i][j] == 'T') found_cow[1][3] = true; } // si un carácter aparece tanto en vacas con manchas como en lisas, devolvemos false // si no hay tal genoma, devolvemos true for (int i = 0; i < 4; ++i) { if (found_cow[0][i] && found_cow[1][i]) return false; } return true; } int main(void) { ifstream fin("cownomics.in"); ofstream fout("cownomics.out"); fin >> N >> M; // leemos la entrada for (int i = 0; i < N; i++) fin >> spotty[i]; for (int i = 0; i < N; i++) fin >> plain[i]; int answer = 0; // probamos cada posición del genoma para ver si podría explicar las manchas for (int j = 0; j < M; j++) if (test_location(j)) answer++; fout << answer << "\n"; return 0; }
import java.io.*; import java.util.StringTokenizer; public class cownomicsBronze { static int N, M; static String[] spotty, plain; static boolean test_location(int j) { boolean[][] found_cow = new boolean[2][4]; // found_cow[0] se refiere a las vacas con manchas, y found_cow[1] a las // vacas sin manchas. found_cow[0][0] = guarda si las vacas con manchas tienen // el carácter A en la posición j found_cow[0][1] = guarda si las vacas con // manchas tienen el carácter C en la posición j found_cow[0][2] = guarda si // las vacas con manchas tienen el carácter G en la posición j found_cow[0][3] = // guarda si las vacas con manchas tienen el carácter T en la posición j found_cow[1][0] = // guarda si las vacas lisas tienen el carácter A en la posición j // found_cow[1][1] = guarda si las vacas lisas tienen el carácter C en // la posición j found_cow[1][2] = guarda si las vacas lisas tienen el carácter // G en la posición j found_cow[1][3] = guarda si las vacas lisas tienen // el carácter T en la posición j // iteramos por las vacas con manchas y actualizamos found_cow[0] for (int i = 0; i < N; i++) { if (spotty[i].charAt(j) == 'A') found_cow[0][0] = true; if (spotty[i].charAt(j) == 'C') found_cow[0][1] = true; if (spotty[i].charAt(j) == 'G') found_cow[0][2] = true; if (spotty[i].charAt(j) == 'T') found_cow[0][3] = true; } // iteramos por las vacas lisas y actualizamos found_cow[1] for (int i = 0; i < N; i++) { if (plain[i].charAt(j) == 'A') found_cow[1][0] = true; if (plain[i].charAt(j) == 'C') found_cow[1][1] = true; if (plain[i].charAt(j) == 'G') found_cow[1][2] = true; if (plain[i].charAt(j) == 'T') found_cow[1][3] = true; } // si un carácter aparece tanto en vacas con manchas como en lisas, devolvemos // false; si no hay tal genoma, devolvemos true for (int i = 0; i < 4; ++i) { if (found_cow[0][i] && found_cow[1][i]) return false; } return true; } public static void main(String[] args) throws IOException { // leemos la entrada BufferedReader br = new BufferedReader(new FileReader("cownomics.in")); PrintWriter out = new PrintWriter("cownomics.out"); StringTokenizer s = new StringTokenizer(br.readLine()); N = Integer.parseInt(s.nextToken()); M = Integer.parseInt(s.nextToken()); spotty = new String[100]; plain = new String[100]; for (int i = 0; i < N; i++) { spotty[i] = br.readLine(); } for (int i = 0; i < N; i++) { plain[i] = br.readLine(); } // probamos cada posición del genoma para ver si podría explicar // las manchas int answer = 0; for (int j = 0; j < M; j++) { if (test_location(j)) answer++; } out.println(answer); out.close(); } }

Solución 1 - Fuerza bruta

Iteramos por cada carácter de cada genoma. Para cada índice de carácter, vemos si hay algún carácter que aparezca en el genoma tanto de una vaca con manchas como de una vaca lisa en ese índice. Si los hay, esta posición no es una solución posible, así que podemos terminar esta parte de la búsqueda y pasar a la siguiente posición para ahorrar tiempo de ejecución. Si no los hay, esta es una solución posible.

Implementación

Complejidad temporal: O(MN2)\mathcal O(MN^2)

#include <fstream> #include <iostream> #include <vector> using std::cout; using std::endl; using std::vector; int main() { std::ifstream read("cownomics.in"); int n; int m; read >> n >> m; // Cada genoma y los caracteres individuales de cada genoma vector<vector<char>> spotted_cows(n, vector<char>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { read >> spotted_cows[i][j]; } } vector<vector<char>> plain_cows(n, vector<char>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { read >> plain_cows[i][j]; } } int poss_positions = 0; // Iteramos por cada carácter for (int i = 0; i < m; i++) { bool dupe = false; // Iteramos por cada genoma for (int j = 0; j < n; j++) { // Comparamos con cada otro genoma for (int k = 0; k < n; k++) { /* * Si hay algún duplicado, * entonces esta no es una posición posible, * así que dejamos de contar y nos aseguramos de no contarla */ if (spotted_cows[j][i] == plain_cows[k][i]) { dupe = true; break; } } } /* * Si no encontramos ningún carácter igual, * entonces no hay duplicados y esta es una secuencia posible */ if (!dupe) { poss_positions++; } } std::ofstream("cownomics.out") << poss_positions << endl; }
import java.io.*; import java.util.*; public class BovineGenomics { public static void main(String[] args) throws IOException { Kattio io = new Kattio("cownomics"); int n = io.nextInt(); int m = io.nextInt(); // Cada genoma y los caracteres individuales de cada genoma char[][] spottedCows = new char[n][]; char[][] plainCows = new char[n][]; for (int i = 0; i < n; i++) { spottedCows[i] = io.next().toCharArray(); } for (int i = 0; i < n; i++) { plainCows[i] = io.next().toCharArray(); } int possPositions = 0; // Iteramos por cada carácter for (int i = 0; i < m; i++) { boolean dupe = false; // Iteramos por cada genoma for (int j = 0; j < n; j++) { // Comparamos con cada otro genoma for (int k = 0; k < n; k++) { /* * Si hay algún duplicado, * entonces esta no es una posición posible, * así que dejamos de contar y nos aseguramos de no contarla */ if (spottedCows[j][i] == plainCows[k][i]) { dupe = true; break; } } } /* * Si no encontramos ningún carácter igual, * entonces no hay duplicados y esta es una secuencia posible */ if (!dupe) { possPositions++; } } io.println(possPositions); io.close(); } // CodeSnip{Kattio} }
with open("cownomics.in", "r") as read: n, m = map(int, read.readline().split()) # Cada genoma y los caracteres individuales de cada genoma spotted_cows = [read.readline() for _ in range(n)] plain_cows = [read.readline() for _ in range(n)] poss_positions = 0 # Iteramos por cada carácter for i in range(m): dupe = False # Iteramos por cada genoma for j in range(n): # Comparamos con cada otro genoma for k in range(n): """ Si hay algún duplicado, entonces esta no es una posición posible, así que dejamos de contar y nos aseguramos de no contarla """ if spotted_cows[j][i] == plain_cows[k][i]: dupe = True break """ Si no encontramos ningún carácter igual, entonces no hay duplicados y esta es una secuencia posible """ if not dupe: poss_positions += 1 print(poss_positions, file=open("cownomics.out", "w"))

Solución 2 - Conjunto hash

Si un genoma está presente en una vaca lisa pero no en una vaca con manchas, incrementamos el resultado. En caso contrario, no es un genoma potencial.

Implementación

Complejidad temporal: O(NM)\mathcal{O}(NM)

#include <fstream> #include <iostream> #include <set> #include <vector> using std::cout; using std::endl; using std::vector; int main() { std::ifstream read("cownomics.in"); int n; int m; read >> n >> m; vector<vector<char>> spotted_cows(n, vector<char>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { read >> spotted_cows[i][j]; } } vector<vector<char>> plain_cows(n, vector<char>(m)); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { read >> plain_cows[i][j]; } } int poss_positions = 0; for (int i = 0; i < m; i++) { std::set<char> seen; for (int j = 0; j < n; j++) { seen.insert(plain_cows[j][i]); } bool dupe = false; for (int j = 0; j < n; j++) { if (seen.count(spotted_cows[j][i]) > 0) { dupe = true; break; } } if (!dupe) { poss_positions++; } } std::ofstream("cownomics.out") << poss_positions << endl; }
import java.io.*; import java.util.*; public class BovineGenomics { public static void main(String[] args) throws IOException { Kattio io = new Kattio("cownomics"); int n = io.nextInt(); int m = io.nextInt(); char[][] spottedCows = new char[n][]; char[][] plainCows = new char[n][]; for (int i = 0; i < n; i++) { spottedCows[i] = io.next().toCharArray(); } for (int i = 0; i < n; i++) { plainCows[i] = io.next().toCharArray(); } int possPositions = 0; for (int i = 0; i < m; i++) { Set<Character> seen = new HashSet<>(); for (int j = 0; j < n; j++) { seen.add(plainCows[j][i]); } boolean dupe = false; for (int j = 0; j < n; j++) { if (seen.contains(spottedCows[j][i])) { dupe = true; break; } } if (!dupe) { possPositions++; } } io.println(possPositions); io.close(); } // CodeSnip{Kattio} }
with open("cownomics.in", "r") as read: n, m = map(int, read.readline().split()) spotted_cows = [read.readline() for _ in range(n)] plain_cows = [read.readline() for _ in range(n)] poss_positions = 0 for i in range(m): seen = set() for j in range(n): seen.add(plain_cows[j][i]) for j in range(n): if spotted_cows[j][i] in seen: break else: poss_positions += 1 print(poss_positions, file=open("cownomics.out", "w"))