Đếm xem có bao nhiêu chuỗi khoảng cách xa tất cả những thứ khác


13

Các khoảng cách Hamming giữa hai chuỗi chiều dài bằng nhau là số vị trí mà tại đó những biểu tượng tương ứng là khác nhau.

Hãy Plà một chuỗi nhị phân có độ dài nTlà một chuỗi nhị phân có độ dài 2n-1. Chúng ta có thể tính nkhoảng cách Hamming giữa Pvà mọi nchuỗi con Tthứ cấp theo thứ tự từ trái sang phải và đặt chúng vào một mảng (hoặc danh sách).

Ví dụ trình tự khoảng cách Hamming

Hãy để P = 101T = 01100. Trình tự khoảng cách Hamming bạn nhận được từ cặp này là 2,2,1.

Định nghĩa về sự gần gũi

Bây giờ hãy xem xét hai chuỗi khoảng cách Hamming như vậy. Nói x = (0, 2, 2, 3, 0)y = (2, 1, 4, 4, 2)làm ví dụ. Chúng tôi nói rằng xyclosenếu y <= x <= 2*yhoặc nếu x <= y <= 2*x. Ở đây phép nhân vô hướng và bất đẳng thức được lấy theo nguyên tố. Đó là để nói, cho hai chuỗi AB, A <= B iff A[i] <= B[i]cho tất cả các chỉ số i.

Lưu ý rằng các chuỗi khoảng cách Hamming tạo thành một thứ tự từng phần theo cách so sánh chúng. Nói cách khác, nhiều cặp trình tự không lớn hơn hoặc bằng hoặc không nhỏ hơn hoặc bằng nhau. Ví dụ (1,2)(2,1).

Vì vậy, sử dụng ví dụ trên, (0, 2, 2, 3, 0) <= 2*(2, 1, 4, 4, 2) = (4, 2, 8, 8, 4)nhưng (0, 2, 2, 3, 0)không lớn hơn (2, 1, 4, 4, 2). Cũng (2, 1, 4, 4, 2)không nhỏ hơn hoặc bằng 2*(0, 2, 2, 3, 0) = (0, 4, 4, 6, 0). Kết quả là xykhông gần nhau.

Bài tập

Để tăng nbắt đầu từ n=1, hãy xem xét tất cả các cặp chuỗi nhị phân có thể có Pđộ dài nTđộ dài 2n-1. Có 2^(n+2n-1)những cặp như vậy và do đó có nhiều chuỗi khoảng cách Hamming. Tuy nhiên, nhiều trong số các chuỗi đó sẽ giống hệt nhau. Nhiệm vụ là tìm kích thước của tập hợp khoảng cách Hamming lớn nhất để không có hai chuỗi gần nhau.

Mã của bạn sẽ xuất ra một số cho mỗi giá trị n.

Ghi bàn

Điểm của bạn nói rộng nhất là nmã của bạn đạt được trên máy của tôi sau 5 phút (nhưng hãy đọc tiếp). Thời gian là cho tổng thời gian chạy, không phải thời gian cho việc đó n.

Để đưa ra điểm số cho câu trả lời không tối ưu, vì việc tìm câu trả lời tối ưu có thể khó, chúng tôi sẽ cần một hệ thống tính điểm hơi tinh tế. Điểm của bạn là giá trị cao nhất nmà không ai khác đã đăng câu trả lời đúng cao hơn cho bất kỳ kích thước nào nhỏ hơn bằng với điều này. Ví dụ: nếu bạn xuất 2, 4, 21và người khác xuất 2, 5, 15thì bạn sẽ chỉ ghi điểm 1vì người khác có câu trả lời tốt hơn n = 2. Nếu bạn xuất ra 2, 5, 21thì bạn sẽ ghi điểm 3bất kể ai khác xuất ra vì những câu trả lời đó đều tối ưu. Rõ ràng nếu bạn có tất cả các câu trả lời tối ưu thì bạn sẽ nhận được điểm cho bài cao nhất nbạn đăng. Tuy nhiên, ngay cả khi câu trả lời của bạn không phải là tối ưu, bạn vẫn có thể đạt được điểm nếu không ai khác có thể đánh bại nó.

Ví dụ câu trả lời và ví dụ làm việc

(Câu trả lời này vẫn chưa được kiểm tra. Xác minh độc lập sẽ được nhận một cách biết ơn.)

Nhờ các sản phẩm ETH:

  • n = 1 cho 2.
  • n = 2 cho 5.
  • n = 3 cho 21.

Hãy xem xét n = 2chi tiết hơn. Trong trường hợp này, danh sách đầy đủ các chuỗi khoảng cách Hamming (được biểu thị bằng các bộ dữ liệu ở đây) là:

[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]

Chúng ta có thể thấy rằng (0,0)nó không gần với bất kỳ bộ dữ liệu nào khác. Trong thực tế, nếu chúng ta lấy (0, 0), (0, 1), (1, 0), (2, 1), (1,2)sau đó không ai trong số những bộ dữ liệu gần gũi với bất kỳ của những người khác. Điều này cho một số điểm 5cho n = 2.

Đối với n = 3danh sách đầy đủ các chuỗi khoảng cách Hamming khác biệt là:

 [(0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 1), (0, 2, 2), (0, 2, 3), (0, 3, 0), (0, 3, 1), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 3, 0), (1, 3, 1), (1, 3, 2), (2, 0, 1), (2, 0, 2), (2, 0, 3), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 2, 0), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 3, 1), (2, 3, 2), (2, 3, 3), (3, 0, 2), (3, 0, 3), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 2, 0), (3, 2, 1), (3, 2, 2), (3, 3, 2), (3, 3, 3)]

Trong các 48chuỗi đó, chúng ta có thể chọn ra một bộ kích thước 21sao cho không có cặp nào trong bộ đó gần nhau.

Ngôn ngữ và thư viện

Bạn có thể sử dụng bất kỳ ngôn ngữ và thư viện có sẵn mà bạn thích. Nếu khả thi, sẽ tốt khi có thể chạy mã của bạn, vì vậy vui lòng bao gồm một lời giải thích đầy đủ về cách chạy / biên dịch mã của bạn trong Linux nếu có thể.

Máy của tôi Thời gian sẽ được chạy trên máy 64 bit của tôi. Đây là bản cài đặt Ubuntu tiêu chuẩn với RAM 8GB, Bộ xử lý tám lõi AMD FX-8350 và Radeon HD 4250. Điều này cũng có nghĩa là tôi cần có khả năng chạy mã của bạn.

Câu trả lời hàng đầu

  • Điểm 4 cho 2, 5, 21, 83, 361 của Christian Sievers. C ++
  • Điểm 5 cho 2, 5, 21, 83, 372 bởi fəˈnɛtɪk. Javascript

Sau khi xem câu hỏi của bạn, nó cho thấy một số điểm tương đồng với các điệp viên, được sửa đổi trên hackerrank, đây là một vấn đề hoàn chỉnh NP
fnɛtɪk

@ fəˈnɛtɪk Tuyệt vời! Lưu ý rằng câu hỏi của tôi không yêu cầu giải pháp tối ưu để đạt điểm cao.

@ fəˈnɛtɪk Bạn cũng có thể xác nhận câu trả lời cho 1,2,3 trong câu hỏi không?

@ fəˈnɛtɪk Tôi rất nghi ngờ đó là NP-hard. Bạn sẽ phải mã hóa Đặt đóng gói hoặc một vấn đề hoàn thành NP khác thành một số nguyên duy nhất chỉ với một thay đổi đa thức về kích thước bài toán.

297 mảng
hamming

Câu trả lời:


5

C ++ sử dụng thư viện igraph

Cảm ơn cho một cơ hội tốt đẹp để tìm hiểu một thư viện mới!

Chương trình này bây giờ tính toán 2, 5, 21, 83, 361nhanh. Bạn có thể kiểm soát việc in các nút với PRINTNODEShằng số.

Biểu đồ được sử dụng có các cạnh phụ giữa các nút tương ứng với các vectơ khoảng cách nơi một gần (nhưng không bằng) với một nút khác đảo ngược. Điều đó tăng tốc tính toán, và bất kỳ tập độc lập nào được tìm thấy tất nhiên cũng là một trong những biểu đồ ban đầu. Ngoài ra, ngay cả khi nó không được thực thi hoàn toàn, bộ độc lập được tính toán sẽ bị đóng dưới sự đảo ngược. Tôi tin rằng luôn tồn tại một tập độc lập tối đa với thuộc tính đó. Ít nhất là có một cho n<=4. (Tôi chắc chắn rằng tôi có thể hiển thị 83 là tối ưu.)

#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
#include<igraph.h>

using vect = std::vector<int>;

constexpr int MAXDIRECT=100;
constexpr int PRINTNODES=1;

std::set<int> avoid{};
igraph_t graph;
std::vector<vect> distance_vectors{};
int count;

int close_h(const vect &a, const vect &b ){
  // check one direction of the closeness condition
  for(auto i=a.begin(), j=b.begin(); i!=a.end(); i++,j++)
    if ( (*i > *j) || (*j > 2 * *i))
      return 0;
  return 1;
}

int close(const vect &a, const vect &b ){
  return close_h(a,b) || close_h(b,a);
}

vect distances(int n, int p, int t){
  vect res{};
  for (int i=0; i<n; ++i){
    int count = 0;
    for (int j=0; j<n; ++j)
      count += 1 & ((p>>j)^(t>>j));
    res.push_back(count);
    t >>= 1;
  }
  return res;
}

void print_vect( vect &v ){
  std::cout << "(";
  auto i=v.begin();
  std::cout << *i++;
  for( ; i!=v.end(); ++i)
    std::cout << "," << *i ;
  std::cout << ")\n";
}

void use_node( int n ){
  if(PRINTNODES)
    print_vect( distance_vectors[n] );
  ++count;
  avoid.insert( n );
  igraph_vector_t neighs;
  igraph_vector_init( &neighs, 0 );
  igraph_neighbors( &graph , &neighs, n, IGRAPH_OUT );
  for(int i=0; i<igraph_vector_size( &neighs ); ++i)
    avoid.insert( VECTOR(neighs)[i] );
  igraph_vector_destroy( &neighs );
}

void construct(int n){
  std::set<vect> dist_vects;
  for(int p=0; p>>n == 0; ++p)
    for(int t=0; t>>(2*n-2) == 0; ++t)   // sic! (because 0/1-symmetry)
      dist_vects.insert(distances(n,p,t));
  int nodes = dist_vects.size();
  std::cout << "distinct distance vectors: " << nodes << "\n";

  distance_vectors.clear();
  distance_vectors.reserve(nodes);
  std::copy(dist_vects.begin(), dist_vects.end(),
            back_inserter(distance_vectors));

  igraph_vector_t edges;
  igraph_vector_init( &edges, 0 );
  igraph_vector_t reversed;
  igraph_vector_init_seq( &reversed, 0, nodes-1 );
  for (int i=0; i<nodes-1; ++i){
    vect &x = distance_vectors[i];
    vect xr ( x.rbegin(), x.rend() );
    for(int j=i+1; j<nodes; ++j){
      vect &y = distance_vectors[j];
      if( xr==y ){
        VECTOR(reversed)[i] = j;
        VECTOR(reversed)[j] = i;
      }else if( close( x, y ) || close( xr, y) ){
        igraph_vector_push_back(&edges,i);
        igraph_vector_push_back(&edges,j);
      }
    }
  }
  std::cout << "edges: " << igraph_vector_size(&edges)/2 << "\n";

  igraph_create( &graph, &edges, nodes, IGRAPH_UNDIRECTED);
  igraph_vector_destroy( &edges );

  igraph_cattribute_VAN_setv( &graph, "r", &reversed );
  igraph_vector_destroy( &reversed );

  igraph_vector_t names;
  igraph_vector_init_seq( &names, 0, nodes-1 );
  igraph_cattribute_VAN_setv( &graph, "n", &names );
  igraph_vector_destroy( &names );

}

void max_independent( igraph_t *g ){
  igraph_vector_ptr_t livs;
  igraph_vector_ptr_init( &livs , 0 );
  igraph_largest_independent_vertex_sets( g, &livs );

  igraph_vector_t *nodes = (igraph_vector_t *) VECTOR(livs)[0];
  igraph_vector_t names;
  igraph_vector_init( &names, 0 );
  igraph_cattribute_VANV( g, "n", igraph_vss_vector( nodes ), &names );

  for(int i=0; i<igraph_vector_size(&names); ++i)
    use_node( VECTOR(names)[i] );
  igraph_vector_destroy( &names );
  igraph_vector_ptr_destroy_all( &livs );
}

void independent_comp( igraph_t *g );

void independent( igraph_t *g ){
  if(igraph_vcount( g ) < MAXDIRECT){
    max_independent( g );
    return;
  }
  igraph_vector_ptr_t components;
  igraph_vector_ptr_init( &components, 0 );
  igraph_decompose( g, &components, IGRAPH_WEAK, -1, 1);
  for(int i=0; i<igraph_vector_ptr_size( &components ); ++i)
    independent_comp( (igraph_t *) VECTOR(components)[i] );
  igraph_decompose_destroy( &components );
}

void independent_comp( igraph_t *g ){
  if (igraph_vcount( g ) < MAXDIRECT){
    max_independent( g );
    return;
  }
  igraph_vector_t degs;
  igraph_vector_init( &degs, 0 );
  igraph_degree( g, &degs, igraph_vss_all(), IGRAPH_OUT, 1 );
  int maxpos = igraph_vector_which_max( &degs );
  igraph_vector_destroy( &degs );  

  int name = igraph_cattribute_VAN( g, "n", maxpos );
  int revname = igraph_cattribute_VAN( g, "r", maxpos );
  int rev = -1;
  if(name!=revname){
    igraph_vector_ptr_t reversed_candidates_singleton;
    igraph_vector_ptr_init( &reversed_candidates_singleton, 0 );
    igraph_neighborhood( g, &reversed_candidates_singleton,
                         igraph_vss_1(maxpos), 2, IGRAPH_OUT );
    igraph_vector_t * reversed_candidates =
      (igraph_vector_t *) VECTOR(reversed_candidates_singleton)[0];
    igraph_vector_t names;
    igraph_vector_init( &names, 0 );
    igraph_cattribute_VANV( g, "n", igraph_vss_vector( reversed_candidates ),
                        &names );
    long int pos;
    igraph_vector_search( &names, 0, revname, &pos );
    rev = VECTOR(*reversed_candidates)[pos];
    igraph_vector_destroy( &names );
    igraph_vector_ptr_destroy( &reversed_candidates_singleton );
  }
  igraph_vs_t delnodes;
  igraph_vs_vector_small( &delnodes, maxpos, rev, -1 );
  igraph_delete_vertices( g, delnodes );
  igraph_vs_destroy( &delnodes );

  independent( g );
}

void handle(int n){
  std::cout << "n=" << n << "\n";
  avoid.clear();
  count = 0;
  construct( n );
  independent( &graph );
  // try all nodes again:
  for(int node=0; node<igraph_vcount( &graph ); ++node)
    if(avoid.count(node)==0)
      use_node(node);
  std::cout << "result: " << count << "\n\n";
  igraph_destroy( &graph );
}

int main(){
  igraph_i_set_attribute_table( &igraph_cattribute_table );
  for(int i=1; i<6; ++i)
    handle(i);
}

Để biên dịch trên debian, cài đặt libigraph0-devvà làm g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o ig ig.cpp -ligraph.

Mô tả cũ:

Thư viện igraph có chức năng tính kích thước tối đa của một tập đỉnh độc lập của đồ thị. Nó có thể xử lý vấn đề này n=3trong chưa đầy một giây và không chấm dứt sau vài ngày n=4.

Vì vậy, những gì tôi làm là phân tách biểu đồ thành các thành phần được kết nối và để thư viện xử lý các thành phần nhỏ (ít hơn MAXDIRECTcác nút). Đối với các thành phần khác, tôi chọn một đỉnh và xóa nó. Trong trường hợp tốt nhất, điều này sẽ chia biểu đồ thành nhiều thành phần, nhưng thường thì không. Dù sao, các thành phần (có thể chỉ có một) nhỏ hơn và chúng ta có thể sử dụng đệ quy.

Rõ ràng việc lựa chọn đỉnh là quan trọng. Tôi chỉ lấy một mức độ tối đa. Tôi thấy rằng tôi nhận được kết quả tốt hơn (nhưng chỉ cho n=4) khi tôi sử dụng danh sách nút đảo ngược. Điều đó giải thích phần ma thuật của constructchức năng.

Nó có thể có giá trị trong khi cải thiện lựa chọn. Nhưng nó có vẻ quan trọng hơn để xem xét lại các nút đã xóa. Ngay bây giờ, tôi không bao giờ nhìn lại họ. Một số trong số chúng có thể không được kết nối với bất kỳ nút nào được chọn. Vấn đề là tôi không biết nút nào tạo thành tập độc lập. Đối với một, xóa các nút làm mới các nút còn lại. Điều đó có thể được xử lý bằng cách gắn attribte với chúng. Nhưng tệ hơn, tính toán của số độc lập chỉ đưa ra con số này. Cách thay thế tốt nhất mà thư viện đưa ra là tính toán tất cả các tập độc lập lớn nhất, tốc độ chậm hơn (dường như phụ thuộc vào kích thước biểu đồ). Tuy nhiên, đây có vẻ là cách ngay lập tức để đi. Mơ hồ hơn nhiều, tôi cũng nghĩ có thể hữu ích để xem xét nếu chúng ta có thể sử dụng cách đặc biệt mà biểu đồ được xác định.

Trường hợp n=6có thể trở nên có thể truy cập (tất cả, không nhất thiết phải trong 5 phút) nếu tôi thay thế đệ quy bằng một vòng lặp bằng cách sử dụng hàng đợi cho các thành phần còn lại.

Tôi thấy thú vị khi nhìn vào các thành phần của đồ thị. Đối với n=4, kích thước của chúng là 168, 2*29, 2*28, 3, 4*2, 4*1. Chỉ có cái lớn nhất không thể được xử lý trực tiếp.

Đối với n=5, kích thước là 1376, 2*128, 2*120, 119, several <=6.

Tôi hy vọng những kích thước gấp đôi đó tương ứng với các đồ thị đẳng hình, nhưng sử dụng cái này có vẻ không đáng giá vì luôn có một thành phần lớn nhất thống trị:

Đối với n=6, thành phần lớn nhất chứa 11941các nút (trong tổng số 15425), hai thành phần lớn nhất tiếp theo có kích thước 596.

Đối với n=7, những con số này là 107593 (125232), 2647.


Bạn có thể cho tôi biết bộ này dành cho 83 không, tôi muốn biết lý do tại sao thuật toán của tôi không đạt được mức cao như vậy cho 4 nhưng bằng cách nào đó sẽ cao hơn cho 5: P
fəˈnɛtɪk

Nó phải được g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o sievers sievers.cpp -ligraph. Điều quan trọng mà -ligraphlà.

@ChristianSievers Làm thế nào để tạo ra các cạnh hoạt động trong mã?
fnɛtɪk

@ChristianSievers Tôi đã tự hỏi làm thế nào nó xác định mỗi đỉnh nên kết nối với cái gì. Đảo ngược mảng có thể làm hỏng nó lên.
fnɛtɪk

@ fəˈnɛtɪk Các vectơ khoảng cách dường như được sắp xếp ra khỏi settôi sử dụng để tránh trùng lặp, nhưng tôi thậm chí không nghĩ về thứ tự của chúng khi tôi viết mã đó. Vòng lặp bên trong bắt đầu i+1chỉ để tránh nhìn vào một cặp và cả phiên bản hoán đổi của nó không cần thiết, và là cách dễ nhất để tránh các vòng lặp (các cạnh (a,a)). Nó không phụ thuộc vào thứ tự mà các nút đến, tôi không quan tâm nếu tôi nhận được (a,b)hoặc (b,a).
Christian Sievers

3

Javascript, Seq: 2,5,21, 81 83,372 67,349

Quản lý để tăng giá trị cho 4 bằng cách sử dụng loại bỏ ngẫu nhiên các yếu tố khi bắt đầu tìm kiếm của tôi. Thật kỳ lạ, loại bỏ 20 yếu tố với hơn 6 kết nối nhanh hơn loại bỏ 5 yếu tố có hơn 8 kết nối ...

Chuỗi này có thể không tối ưu cho 5 và có thể không tối ưu cho 4. Không có nút nào gần với nút khác trong tập hợp.

Mã số:

input=4;
maxConnections=6;
numRand=20;

hammings=[];
h=(x,y)=>{retVal=0;while(x||y){if(x%2!=y%2)retVal++;x>>=1;y>>=1}return retVal};
for(i=1<<(input-1);i<1<<input;i++){
  for(j=0;j<1<<(2*input);j++){
    hamming=[];
    for(k=0;k<input;k++){
      hamming.push(h((j>>k)%(1<<input),i));
    }
    equal=0;
    for(k=0;k<hammings.length;k++){
      if(hamming.join("")==hammings[k].join("")){
        equal=1;
        break;
      }
    }
    if(!equal)hammings.push(hamming);
  }
}
adjMat=[];
for(i=0;i<Math.pow(input+1,input);i++){
  row=[];
  for(j=0;j<Math.pow(input+1,input);j++){
    row.push(0);
  }
  adjMat.push(row);
}
nodes=[]
for(i=0;i<Math.pow(input+1,input);i++){
  nodes[i]=0;
}
for(i=0;i<hammings.length;i++){
  sum=0;
  chkNodes=[[]];
  for(j=0;j<input;j++){
    chkVal=[];
    t=Math.pow(input+1,j);
    sum+=t*hammings[i][j];
    tmp=[];
    for(r=0;r<chkNodes.length;r++){
      for(k=hammings[i][j];k<=Math.min(hammings[i][j]*2,input);k++){
        stor=[]
        for(s=0;s<chkNodes[r].length;s++){
          stor.push(chkNodes[r][s])
        }
        stor.push(k)
        tmp.push(stor);
      }
    }
    chkNodes=[];
    for(r=0;r<tmp.length;r++){
      chkNodes.push(tmp[r])
    }
  }
  nodes[sum]=1;
  for(j=0;j<chkNodes.length;j++){
    adjSum=0
    for(k=0;k<input;k++){
      adjSum+=Math.pow(input+1,k)*chkNodes[j][k]
    }
    if(adjSum!=sum)adjMat[sum][adjSum]=adjMat[adjSum][sum]=1
  }
}
t=nodes.length;
for(i=0;i<t;i++){
  if(!nodes[i]){
    for(k=0;k<t;k++){
      adjMat[i][k]=adjMat[k][i]=0
    }
  }
}
sum=(a,b)=>a+b;
console.log(nodes.reduce(sum))
connections=x=>x.reduce(sum)
counts=adjMat.map(connections);
stor=[];
for(i=0;i<t;i++){
  stor.push(nodes[i]);
}
maxRemainder=0;

greater=[]
for(i=0;i<t;i++){
  if(nodes[i]&&counts[i]>maxConnections){
    greater.push(i);
  }
}

if(input==4){
  for(w=0;w<greater.length*numRand;w++){
    for(i=0;i<t;i++){
      nodes[i]=stor[i];
    }
    counts=adjMat.map(connections);
    toRemove=Math.floor(Math.random()*numRand*2)
    for(i=0;i<toRemove&&i<greater.length;i++){
      rand=Math.floor(Math.random()*greater.length);
      if(nodes[greater[rand]]){
        nodes[greater[rand]]=0;
        for(j=0;j<t;j++){
          if(adjMat[rand][j]){
            counts[j]--;
          }
        }
      }
    }

    for(i=0;i<t*t;i++){
      max=0;
      maxLoc=0;
      for(j=0;j<t;j++){
        if(counts[j]>=max&&nodes[j]){
          max=counts[j];
          maxLoc=j;
        }
      }
      if(max>0){
        for(j=0;j<t;j++){
          if(adjMat[maxLoc][j]){
            counts[j]--;
            if(counts[j]<max-1&&stor[j]&&!nodes[j]){
              nodes[j]=1;
              for(k=0;k<t;k++){
                if(adjMat[j][k])counts[k]++;
              }
            }
          }
          nodes[maxLoc]=0;
        }
      }
      else{
        break;
      }
    }
    maxRemainder=Math.max(maxRemainder,nodes.reduce(sum))
    //console.log(nodes.reduce(sum));
  }
  console.log(maxRemainder);
}
else{
  for(i=0;i<t*t;i++){
    max=0;
    maxLoc=0;
    for(j=0;j<t;j++){
      if(counts[j]>=max&&nodes[j]){
        max=counts[j];
        maxLoc=j;
      }
    }
    if(max>0){
      for(j=0;j<t;j++){
        if(adjMat[maxLoc][j]){
          counts[j]--;
          if(counts[j]<max-1&&stor[j]&&!nodes[j]){
            nodes[j]=1;
            for(k=0;k<t;k++){
              if(adjMat[j][k])counts[k]++;
            }
          }
        }
        nodes[maxLoc]=0;
      }
    }
    else{
      break;
    }
  }
  console.log(nodes.reduce(sum));
}

Hãy thử trực tuyến!

Đoạn trích có thể được thêm vào cuối chương trình để hiển thị chuỗi khoảng cách Hamming nào cho mỗi chuỗi khoảng cách Hamming đã chọn

for(i=0;i<t;i++){
  if(nodes[i]){
    tmp=[]
    for(j=0;j<input;j++){
      tmp.unshift(Math.floor(i/Math.pow(input+1,j))%(input+1))
    }
    console.log(tmp.join(""))
    output=""
    for(j=0;j<t;j++){
      if(adjMat[i][j]&&stor[j]){
        outArr=[]
        for(k=0;k<input;k++){
          outArr.unshift(Math.floor(j/Math.pow(input+1,k))%(input+1))
        }
        output+=" "+outArr.join("");
      }
    }
    console.log(output)
  }
}

Giải trình:

Đầu tiên, mã tạo ra tất cả các khoảng cách hãm độc đáo từ các chuỗi con.

input=3;
hammings=[];
h=(x,y)=>{retVal=0;while(x||y){if(x%2!=y%2)retVal++;x>>=1;y>>=1}return retVal};
for(i=1<<(input-1);i<1<<input;i++){
  for(j=0;j<1<<(2*input);j++){
    hamming=[];
    for(k=0;k<input;k++){
      hamming.push(h((j>>k)%(1<<input),i));
    }
    equal=0;
    for(k=0;k<hammings.length;k++){
      if(hamming.join("")==hammings[k].join("")){
        equal=1;
        break;
      }
    }
    if(!equal)hammings.push(hamming);
  }
}

Tiếp theo, mã chuyển đổi danh sách này thành một biểu đồ vô hướng

adjMat=[];
for(i=0;i<Math.pow(input+1,input);i++){
  row=[];
  for(j=0;j<Math.pow(input+1,input);j++){
    row.push(0);
  }
  adjMat.push(row);
}
nodes=[]
for(i=0;i<Math.pow(input+1,input);i++){
  nodes[i]=0;
}
for(i=0;i<hammings.length;i++){
  sum=0;
  chkNodes=[[]];
  for(j=0;j<input;j++){
    chkVal=[];
    t=Math.pow(input+1,j);
    sum+=t*hammings[i][j];
    tmp=[];
    for(r=0;r<chkNodes.length;r++){
      for(k=hammings[i][j];k<=Math.min(hammings[i][j]*2,input);k++){
        stor=[]
        for(s=0;s<chkNodes[r].length;s++){
          stor.push(chkNodes[r][s])
        }
        stor.push(k)
        tmp.push(stor);
      }
    }
    chkNodes=[];
    for(r=0;r<tmp.length;r++){
      chkNodes.push(tmp[r])
    }
  }
  nodes[sum]=1;
  for(j=0;j<chkNodes.length;j++){
    adjSum=0
    for(k=0;k<input;k++){
      adjSum+=Math.pow(input+1,k)*chkNodes[j][k]
    }
    if(adjSum!=sum)adjMat[sum][adjSum]=adjMat[adjSum][sum]=1
  }
}

Cuối cùng, mã quay vòng qua biểu đồ này, loại bỏ đỉnh với hầu hết các kết nối mỗi chu kỳ trước khi khôi phục bất kỳ nút nào hiện có ít kết nối hơn mức tối đa hiện tại. Khi kết thúc chu trình này, nó xuất ra số nút còn lại

t=nodes.length;
for(i=0;i<t;i++){
  if(!nodes[i]){
    for(k=0;k<t;k++){
      adjMat[i][k]=adjMat[k][i]=0
    }
  }
}
sum=(a,b)=>a+b;
counts=adjMat.map(x=>x.reduce(sum));
stor=[];
for(i=0;i<t;i++){
  stor.push(nodes[i]);
}
for(i=0;i<t*t;i++){
  max=0;
  maxLoc=0;
  for(j=0;j<t;j++){
    if(counts[j]>=max&&nodes[j]){
      max=counts[j];
      maxLoc=j;
    }
  }
  if(max>0){
    for(j=0;j<t;j++){
      if(adjMat[maxLoc][j]){
        counts[j]--;
        if(counts[j]<max-1&&stor[j]&&!nodes[j]){
          nodes[j]=1;
          for(k=0;k<t;k++){
            if(adjMat[j][k])counts[k]++;
          }
        }
      }
      nodes[maxLoc]=0;
    }
  }
  else{
    break;
  }
}
console.log(nodes.reduce(sum));

Bộ:

1:

0 1

2:

00 01 10 12 21

3:

000 001 011 013 030 031 100 101 110 111 123 130 132 203 213 231 302 310 312 
321 333

4:

0000 0001 0011 0111 0124 0133 0223 0230 0232 0241 0313 0320 0322 0331 0403 
0412 1000 1001 1013 1021 1100 1102 1110 1111 1134 1201 1224 1233 1243 1304 
1314 1323 1330 1332 1342 1403 1413 1420 1422 2011 2033 2124 2133 2140 2142 
2214 2230 2241 2303 2313 2320 2331 2411 3023 3032 3040 3041 3101 3114 3123 
3130 3132 3141 3203 3213 3220 3231 3302 3310 3312 3321 3334 3343 3433 4031 
4113 4122 4131 4210 4212 4221 4311 4333

5:

00000 00001 00011 00111 00123 01112 01235 01244 01324 01343 02111 02230 
02234 02333 02342 02432 02441 02522 02530 02531 03134 03142 03220 03224 
03233 03241 03314 03323 03331 03403 03412 03421 03520 04133 04141 04214 
04223 04232 04303 04313 04322 05042 05050 05051 05132 10000 10001 10011 
10122 10212 10221 10245 11000 11001 11013 11022 11100 11112 11120 11121 
11202 11211 11345 11353 11443 12012 12111 12201 12245 12253 12335 12344 
12352 12425 12430 12434 12442 12513 12532 13033 13042 13244 13252 13325 
13330 13334 13342 13404 13424 13433 13441 13520 13522 13531 14032 14051 
14140 14152 14225 14230 14234 14241 14243 14304 14315 14324 14332 14413 
14420 14422 14431 15041 15050 15125 15133 15142 15215 15223 15232 20112 
20135 20211 20253 20334 20352 21012 21021 21102 21110 21111 21201 21245 
21344 21352 21430 21433 21442 21514 21523 22011 22101 22135 22244 22252 
22325 22334 22340 22343 22405 22415 22424 22441 22520 22522 22531 23041 
23144 23150 23152 23225 23234 23240 23243 23251 23304 23315 23324 23333 
23341 23403 23413 23420 23432 23521 24031 24050 24125 24130 24134 24142 
24151 24215 24224 24233 24303 24314 24320 24323 24331 24412 24421 25123 
25132 25141 25203 25214 25222 25231 25302 25312 25321 30234 30243 30252 
30324 30333 30340 30342 30414 30423 30430 30432 31011 31235 31244 31253 
31325 31334 31340 31343 31405 31415 31424 31432 31441 31504 31521 32025 
32034 32100 32144 32152 32225 32234 32240 32243 32251 32304 32315 32324 
32330 32333 32342 32403 32414 32423 32512 33024 33031 33033 33125 33134 
33140 33143 33151 33215 33224 33230 33233 33242 33303 33314 33320 33323 
33332 33412 33431 34124 34133 34203 34214 34223 34232 34241 34310 34313 
34322 34411 35202 35213 35221 35311 40323 40332 40341 40431 40505 40513 
41135 41144 41240 41243 41252 41324 41330 41333 41342 41403 41414 41423 
41512 42033 42134 42143 42230 42233 42242 42303 42310 42314 42323 42332 
42341 42413 42422 42431 43023 43124 43130 43133 43142 43203 43220 43223 
43232 43241 43302 43313 43322 43331 43421 44114 44123 44132 44210 44213 
44222 44231 44312 44321 50413 50422 50504 51233 51242 51251 51323 51332 
51341 51413 51422 52023 52133 52142 52151 52223 52232 52241 52313 52322 
52331 52421 53102 53114 53122 53210 53213 53321 54201 54212 54221 54311

Cảm ơn đã cho câu trả lời đầu tiên! Bạn có thể hướng dẫn từng bước cho những kẻ ngốc về cách chạy mã của bạn trong Linux không?

Có lẽ fəˈnɛtɪk có thể biến mã của mình thành một đoạn trích?
mbomb007

@ mbomb007 vì một số lý do, biến điều này thành một đoạn trích gây ra lỗi 0 không phải là một hàm ... trong dòng cho (j = 0; j <t; j ++)
fəˈnɛtɪk

Có lẽ bạn có thể thử JSFiddle?
mbomb007

Nếu bạn có chrome, bạn có thể sao chép dán mã vào bảng điều khiển và chạy nó bằng cách nhấn enter. Không hoàn toàn chắc chắn về các trình duyệt khác. Chrome chạy mã nhanh hơn các hệ thống trực tuyến đối với tôi. Được quản lý để nhận giá trị thứ 5 là 349
fəˈnɛtɪk
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.