2016년 11월 24일 목요일

MongoDB 설치 후 저장 디렉토리 변경 주의사항

MongoDB를 설치하기 위해 공식 도큐먼트(https://docs.mongodb.com/.../install-mongodb-on-ubuntu/)를 참고하였다.

정상적으로 설치된 것을 확인하고 이후에 기본 저장 디렉토리를 변경하기 위해서 /etc/mongod.conf 파일을 건드렸다.

# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# Where and how to store data.
storage:
#  dbPath: /var/lib/mongodb
  dbPath: /data/mongodb
  journal:
    enabled: true
#  engine:
#  mmapv1:
#  wiredTiger:

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1


#processManagement:

#security:

#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options:

#auditLog:

#snmp:

dbpath를 /data/mongodb 로 변경하고 /data/mongodb 디렉토리를 만들어줬다.

$ sudo mkdir /data && sudo mkdir /data/mongodb

그리고 다시 mongodb를 구동하면 실행에 실패한다.

$ sudo service mongod status
● mongod.service - High-performance, schema-free document-oriented database
   Loaded: loaded (/lib/systemd/system/mongod.service; disabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Thu 2016-11-24 04:49:20 UTC; 3s ago
     Docs: https://docs.mongodb.org/manual
  Process: 5335 ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf (code=exited, status=100)
 Main PID: 5335 (code=exited, status=100)

mongodb에서 해당 디렉토리에 접근 권한이 없기 때문이다.

다음과 같이 권한을 추가해주면 정상적으로 구동된다.

$ chown mongodb:mongodb /data/mongodb

정상적으로 작동하는 모습

$ sudo service mongod status
● mongod.service - High-performance, schema-free document-oriented database
   Loaded: loaded (/lib/systemd/system/mongod.service; disabled; vendor preset: enabled)
   Active: active (running) since Thu 2016-11-24 04:50:04 UTC; 5s ago
     Docs: https://docs.mongodb.org/manual
 Main PID: 5420 (mongod)
    Tasks: 17
   Memory: 32.1M
      CPU: 130ms
   CGroup: /system.slice/mongod.service
           └─5420 /usr/bin/mongod --quiet --config /etc/mongod.conf

2016년 11월 1일 화요일

2022 - 사다리

https://www.acmicpc.net/problem/2022
https://uva.onlinejudge.org/...&problem=1507


\(a, b, c\) 가 주어지면 \(k\) 를 구해내는 문제이다.

피타고라스로 A, B를 구해서 기울기를 구하고, 두 직선의 교점 방정식을 이용했다. 그리고 교점의 y 위치가 \(c\) 가 되는 순간을 구하도록 이분 탐색을 했다.

우선 a가 포함된 직선을 g(x), b가 포함된 직선을 f(x)라 한다면 아래와 같은 정보가 나온다.

\(
\begin{cases}
A = \sqrt{a^2 - k^2} \\
B = \sqrt{b^2 - k^2}
\end{cases}
\)

\(
\begin{cases}
f(x) = \frac{B}{k}x \\
g(x) = -\frac{A}{k}x+A
\end{cases}
\)

두 직선이 만나는 순간을 \( (c_0, c) \)라 한다면 \( f(c_0) = g(c_0) = c \) 이여야 한다.

\(
\begin{align}
f(c_0) = & \frac{B}{k}c_0 = c \\
& c_0 = \frac{k \cdot c}{B}
\end{align}
\)

\(g(c_0) = g(\frac{k \cdot c}{B}) = c\) 가 나온다면 정답일것이다.

k를 찾는 과정에서 \(f(c_0) \gt c\) 라면 높이가 더 높은 좌표이므로 \(c_0\)을 줄여야한다는 뜻이다. k를 줄이면 \(c_0\)도 줄어든다.

k를 조정해서 만들어진 적당한 x로 f(x) = g(x)가 성립하는 지 확인하면서, 결과에 따라 k를 다시 조정하면 정답이 나온다.

k를 찾는 구간을 줄일 때 epsilon을 1e-5로 설정했을 때는 오답이었다. 이분탐색이 중간에 잘못되고 있나 생각에 구글링하다가 더 작은 결과까지 해보도록 1e-9 로 바꿨더니 정답을 맞았다. 너무 허무함

#include <bits/stdc++.h>
using namespace std;

#define INF 987654321

double a, b, c;

double g(double x, double k){
    double A = sqrt(a*a - k*k);
    return A - (A * x / k);
}

double f(double x, double k){
    return sqrt(b*b - k*k) * x / k;
}

int main(){
    while(~scanf("%lf %lf %lf", &a, &b, &c)){
        double l=0, r=min(a, b);
        
        while(r - l > 1e-9){
            double k = (l+r)/2.0;
            double c0 = k * c / sqrt(b*b - k*k);
            if(g(c0, k) > c){
                l = k;
            } else {
                r = k;
            }
        }
        
        printf("%.3lf\n", l);
    }
    return 0;
}

1939 - 중량제한

https://www.acmicpc.net/problem/1939

S에서 E로 가는 데, 한 번의 이동에서 옮길 수 있는 물품들의 중량의 최대값을 구한다.

문제를 읽고 왠지 이거 다익스트라처럼 그리디하게 풀면 풀리겠다 싶어서 그래프 몇개 끄적거렸는데 무한루프에 빠질것만 같은 공포에 휩싸였다.

dp를 적용하자니 다리의 중량제한 \(c(1 \le c \le 10^9)\) 라서 안되겠다싶었고.

그럼 스패닝 트리를 만들어볼까해서 프림을 생각했는데 몇 개 적어놨던 예제에서부터 안됐다.

그래도 트리로 만드는게 가장 정답같아서 크루스칼로 구현했는데 정답이었다.

크루스칼로 최대 스패닝 트리를 만들고, S에서 E로 가는 경로 중에 가장 중량제한이 작은 것을 출력한다.

#include <bits/stdc++.h>
using namespace std;

#define INF 987654321

typedef pair<int,int> ii;

struct edge {
    int u, v, d;
    bool operator < (const edge& e) const {
        return d < e.d;
    }
};

vector<edge> E;

int group[100001];

int find(int v){
    if(v != group[v])
        return (group[v] = find(group[v]));
    return v;
}

bool Union(int p, int q){
    p = find(p);
    q = find(q);
    if(p == q) return false;
    group[q] = p;
    return true;
}

vector<ii> adj[100001];

bool visit[100001];
int answer(int pos, int dst, int m = INF){
    if(pos == dst) return m;
    
    if(visit[pos]) return 0;
    visit[pos] = true;
    
    for(auto& v : adj[pos]){
        int r = answer(v.first, dst, min(v.second, m));
        if(r != 0) return r;
    }
    return 0;
}

int main(){
    int n, m;
    scanf("%d %d", &n, &m);
    while(m--){
        int a, b, c;
        scanf("%d %d %d", &a, &b, &c);
        E.push_back({a-1, b-1, c});
    }
    sort(E.rbegin(), E.rend());
    
    for(int i=0; i<n; ++i) group[i] = i;
    
    for(auto& e : E){
        if( Union(e.u, e.v) ){
            adj[e.u].push_back(ii(e.v, e.d));
            adj[e.v].push_back(ii(e.u, e.d));
        }
    }
    
    int src, dst;
    scanf("%d %d", &src, &dst);
    printf("%d", answer(src-1, dst-1));
    
    return 0;
}

다른 사람들 정답 코드를 보니까 다익스트라도 있었는데, 크루스칼로 푼 사람들 중에 하나를 보고 배웠다.

S에서 E로 가는 경로를 다시 탐색할 필요가 없이, S가 속한 집합과 E가 속한 집합이 같아지는 시점에 연결하는 간선의 중량이 "가능한 가장 큰 중량제한"이었다.

#include <bits/stdc++.h>
using namespace std;
 
#define INF 987654321
 
typedef pair<int,int> ii;
 
struct edge {
    int u, v, d;
    bool operator < (const edge& e) const {
        return d < e.d;
    }
};
 
vector<edge> E;
 
int group[100001];
 
int find(int v){
    if(v != group[v])
        return (group[v] = find(group[v]));
    return v;
}

int main(){
    int n, m;
    scanf("%d %d", &n, &m);
    while(m--){
        int a, b, c;
        scanf("%d %d %d", &a, &b, &c);
        E.push_back({a-1, b-1, c});
    }
    sort(E.rbegin(), E.rend());
     
    for(int i=0; i<n; ++i) group[i] = i;
     
    int src, dst;
    scanf("%d %d", &src, &dst);
     
    for(auto& e : E){
        group[find(e.u)] = find(e.v);
        if( find(src-1) == find(dst-1) ){
            printf("%d", e.d);
            break;
        }
    }
     
    return 0;
}

게시글 목록