// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;



#define int long long



int n;

string s;

vector<int> v; // sを数値に変換した配列。#は1で.は0

int dp[222222][5]; // dp[i][j]: 直前の要素がjで、i番目の要素まで見た時の最小の操作回数



int dfs(int idx, int old) {

  if (idx >= v.size()) {

    return 0;

  }



  if (dp[idx][old] != -1) {

    return dp[idx][old];

  }



  int ret = 0;



  int a = dfs(idx+1, 1) + (v[idx] == 0); // 現在の要素を'#'にする

  int b = (old == 1 ? 1e18 : dfs(idx+1, 0) + (v[idx] == 1)); // 現在の要素を'.'にする

  ret += min(a, b);



  return dp[idx][old] = ret;

}



signed main() {

  cin >> n >> s;

  v.push_back(-1); // つじつま合わせ的なやつ

  for (int i = 0; i < n; i++) {

    int val = s[i] == '#' ? 1 : 0; // ここから先では「#」を1、「.」を0として扱う

    v.push_back(val);

  }



  // dpテーブルを初期化

  for (int i = 0; i < 222222; i++) { for (int j = 0; j < 5; j++) { dp[i][j] = -1; } }



  int ans = dfs(0, 3); // 3は0番目の要素の前の要素がどの記号化を表す。-1番目の要素は存在しないので適当に3と置いた



  cout << ans << endl;



  return 0;

}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

using namespace std;



#define int long long

#define vvi vector<vector<int>>

#define vec vector

#define pq priority_queue

#define all(v) (v).begin(), (v).end()

#define uniqueV(x) sort(x.begin(), x.end()); x.erase(unique(x.begin(), x.end()), x.end());

#define rep(i, n) for (int (i) = (0); (i) < (n); ++(i))

#define repp(i, m, n) for (int (i) = (m); (i) < (n); ++(i))

#define dbg(x) cerr << #x << ": " << x << endl;

#define dbg2(x, y) cerr<<"("<<#x<<", "<<#y<<") = "<<"("<<x<<", "<<y<<")"<<endl;

#define dbg3(x, y, z) cerr<<"("<<#x<<", "<<#y<<", "<<#z<<") = "<<"("<<x<<", "<<y<<", "<<z<<")"<<endl;

#define dbgB(value, size) cerr<<#value<<": "<<bitset<size>(value) << endl;

#define line() cerr << "---------------" << endl;



const int dx[] = {1, -1, 0, 0};

const int dy[] = {0, 0, -1, 1};

const double PI = 3.14159265358979323846;



template<class T>bool chmax(T &a, const T &b) { if (a<b) { a = b; return 1; } return 0; }

template<class T>bool chmin(T &a, const T &b) { if (b<a) { a = b; return 1; } return 0; }



template<typename T>

void print1(T begin, T end) {

  while (begin != end) {

    cerr << (*begin) << " ";

    *begin++;

  }

  cerr << endl;

}



template<typename T>

void print2(T Array, int height, int width) {

  for (int i = 0; i < height; i++) {

    for (int j = 0; j < width; j++) {

      cerr << " " << Array[i][j];

    }

    cerr << endl;

  }

}



void print() { std::cerr << endl; }

template <class Head, class... Tail>

void print(Head&& head, Tail&&... tail) {

  std::cerr << head << " ";

  print(std::forward<Tail>(tail)...);

}



template<class T>

void Add(T &a, const T &b, const T &mod=1000000007) {

  int val = ((a % mod) + (b % mod)) % mod;

  if (val < 0) { val += mod; }

  a = val;

}



template <typename X, typename T> auto vectors(X x, T a) { return vector<T>(x, a); }

template <typename X, typename Y, typename Z, typename... Zs> auto vectors(X x, Y y, Z z, Zs... zs) { auto cont = vectors(y, z, zs...); return vector<decltype(cont)>(x, cont); }



// ------------------------------------------------------------------------------------------



int N;

string s;

int white[222222];

int black[222222];



signed main() {

  cin >> N >> s;

  rep (i, N) {

    white[i+1] = s[i] == '.';

    black[i+1] = s[i] == '#';

  }



  for (int i = 0; i <= N; i++) {

    black[i+1] += black[i];

  }

  for (int i = N; i >= 1; i--) {

    white[i-1] += white[i];

  }



  int ans = 1e18;

  rep (i, N+1) {

    int t = black[i] + white[i+1];

    chmin(ans, t);

  }

  // print1(black, black+N+1);

  // print1(white, white+N+1);



  cout << ans << endl;



  return 0;

}

// Fastest known solution for this problem: